Commit 30ababda by Szeberényi Imre

MPI implementation of Eratosthenes's sieve, but not parallelized.

It could be used as a skeleton for data-paralell implementation
parents
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="myprime_s" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/myprime_s" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/myprime_s" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add directory="$(#msmpi.include)" />
</Compiler>
<Linker>
<Add library="msmpi" />
<Add directory="$(#msmpi.lib)/x64" />
</Linker>
<Unit filename="myprime_serial.cpp" />
<Unit filename="myutils.hpp" />
<Extensions>
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* \file: myprime_serial.cpp (Without MPI C++ API)
*
* serial, but MPI implementation of Eratosthenes's sieve
* It could be used as a skeleton for data-paralell implementation
*
*/
#include <iostream>
#include <mpi.h>
#include <vector>
#include "myutils.hpp"
// Indexable array for storing bits.
// Default value is 0
// Index range: [low..high]
// Out-of-rage indexing returns 0
class BitArray {
size_t low; // low index value
size_t high; // high index value
std::vector<bool> s;// bitvector
std::vector<bool>::reference dummy; // used as lvalue at out of range
public:
BitArray(size_t low, size_t high) :low(low), high(high), s(high-low+1) {}
bool operator[](size_t i) const {
if (i >= low && i <= high) return s[i-low];
else return false;
}
std::vector<bool>::reference operator[](size_t i) {
if (i >= low && i <= high) return s[i-low];
else return dummy;
}
};
#define N 100
int main(int argc, char ** argv) {
debMsg cout(std::cout); // this is the own cout for debugging
size_t n = N;
if (argc > 1) n = atoi(argv[1]);
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// set the debug id
{
std::stringstream id;
id << "PROC" << rank << "> ";
cout.setid(id.str());
}
Stopwatch watch;
BitArray V(2, n);
size_t m = 2;
while (m*m < n) {
if (V[m] == false) {
size_t i = m*m;
while (i <= n) {
V[i] = true;
i = i+m;
}
}
m = m+1;
}
// The results should be collected from parallel parts
// ...
// Writes elapsed time to separate stream (to cerr)
std::cerr << "Elapsed time:" << watch.elapsed() << "sec" << endl;
// Prints the resuls
cout << "Primes in [1.." << n << "]:\n";
if (argc <= 2) { // argc >2 supress the output
for (size_t i = 2; i <= n; i++)
if (V[i] == false)
cout << " " << i;
}
cout << endl;
MPI_Finalize();
return 0;
}
/**
* \file: myutils.hpp
*
* usleep function
* debMsg class
*
*/
#ifndef MYUTILS_INLUDED
#define MYUTULS_INLUDED
#include <iostream>
#include <sstream>
#include <string>
#include <unistd.h>
#include <chrono>
#include <thread>
/// microsecond sleep
/// @param t - time to sleep in useconds
void uSleep(int usec) {
std::this_thread::sleep_for(std::chrono::microseconds(usec));
}
/// debMsg class for debugging.
/// Collects the output and inserts to the stream when the flush() is called.
/// In this way the outputs of differnt parallel tasks will not mixed (hopefully).
class debMsg : public std::stringstream {
std::ostream& os;
std::string id;
public:
debMsg(std::ostream& s = std::cerr, const std::string& id = "")
:os(s), id(id) {
*this << id;
std::setvbuf(stdout, NULL, _IOFBF, BUFSIZ);
}
void flush() {
if (this->str() == id) return;
(os << this->str()).flush();
this->str(""); // clear the string
*this << id;
}
void setid(const std::string& id = "") {
this->id = id;
flush();
}
~debMsg() { flush(); }
};
/// My endl
class endl_t {} endl;
/// My endline inserted to the stream
std::ostream& operator<<(std::ostream& os, endl_t) {
os.put('\n'); // newline
try {
dynamic_cast<debMsg&>(os).flush(); // convertable -> calls flush()
} catch (std::bad_cast&) {
os.flush(); // can't cast
}
return os;
}
class Stopwatch {
double sec0;
public:
Stopwatch() : sec0(MPI_Wtime()) {}
double elapsed() {
double sec1 = MPI_Wtime();
double sec = sec1 - sec0;
sec0 = sec1;
return sec;
}
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment