diff --git a/Serie07/pi/Makefile b/Serie07/pi/Makefile index 9f2231e..2677738 100644 --- a/Serie07/pi/Makefile +++ b/Serie07/pi/Makefile @@ -1,12 +1,14 @@ -OPTIM+=-O3 -march=native -CXX=g++ -CC=g++ +OPTIM+=-O3 + +CXX=mpicxx +CC=mpicxx LD=${CXX} CXXFLAGS+=-Wall -Wextra -std=c++11 $(OPTIM) -LDFLAGS+=-lm -EXE=pi +LDFLAGS+=$(OPTIM) -lm + +EXECS=pi_gather pi_p2p_async_ring -all: clean $(EXE) +all: clean $(EXECS) clean: - rm -f $(EXE) *.o *~ + rm -f $(EXECS) *.o *~ diff --git a/Serie07/pi/pi.cc b/Serie07/pi/pi.cc deleted file mode 100644 index 1857d6b..0000000 --- a/Serie07/pi/pi.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - This exercise is taken from the class Parallel Programming Workshop (MPI, - OpenMP and Advanced Topics) at HLRS given by Rolf Rabenseifner - */ - -#include -#include -#include - -using clk = std::chrono::high_resolution_clock; -using second = std::chrono::duration; -using time_point = std::chrono::time_point; - -inline int digit(double x, int n) { - return std::trunc(x * std::pow(10., n)) - std::trunc(x * std::pow(10., n - 1)) *10.; -} - -inline double f(double a) { return (4. / (1. + a * a)); } - -const int n = 10000000; - -int main(int /* argc */ , char ** /* argv */) { - int i; - double dx, x, sum, pi; - - auto t1 = clk::now(); - - /* calculate pi = integral [0..1] 4 / (1 + x**2) dx */ - dx = 1. / n; - sum = 0.0; - for (i = 0; i < n; i++) { - x = 1. * i * dx; - sum = sum + f(x); - } - pi = dx * sum; - - second elapsed = clk::now() - t1; - - std::printf("computed pi = %.16g\n", pi); - std::printf("wall clock time (chrono) = %.4gs\n", elapsed.count()); - - for(int d = 1; d <= 15; ++d) { - std::printf("%d", digit(pi, d)); - } - - return 0; -} diff --git a/Serie07/pi/pi_gather.cc b/Serie07/pi/pi_gather.cc new file mode 100644 index 0000000..978c4a4 --- /dev/null +++ b/Serie07/pi/pi_gather.cc @@ -0,0 +1,82 @@ +/* + This exercise is taken from the class Parallel Programming Workshop (MPI, + OpenMP and Advanced Topics) at HLRS given by Rolf Rabenseifner + */ + +#include +#include +#include +#include +#include + +using clk = std::chrono::high_resolution_clock; +using second = std::chrono::duration; +using time_point = std::chrono::time_point; + +inline int digit(double x, int n) { + return std::trunc(x * std::pow(10., n)) - std::trunc(x * std::pow(10., n - 1)) *10.; +} + +inline double f(double a) { return (4. / (1. + a * a)); } + +const int n = 10000000; + +int main(int /* argc */ , char ** /* argv */) { + int i; + double dx, x, sum, pi; + int psize, prank; + + MPI_Init(NULL, NULL); + + MPI_Comm_size(MPI_COMM_WORLD, &psize); + MPI_Comm_rank(MPI_COMM_WORLD, &prank); + + auto mpi_t1 = MPI_Wtime(); + auto t1 = clk::now(); + + int nlocal = n / psize; + int istart = 1 + nlocal * prank; + int iend = nlocal * (prank + 1); + + /* calculate pi = integral [0..1] 4 / (1 + x**2) dx */ + dx = 1. / n; + sum = 0.0; + for (i = istart; i <= iend; i++) { + x = (1. * i - 0.5) * dx; + sum = sum + f(x); + } + + if(prank == 0) { + std::vector sums(psize); + MPI_Gather(&sum, 1, MPI_DOUBLE, sums.data(), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + sum = 0.; + for(auto s : sums) { + sum += s; + } + + } else { + MPI_Gather(&sum, 1, MPI_DOUBLE, NULL, 0, MPI_DOUBLE, 0, MPI_COMM_WORLD); + } + + MPI_Bcast(&sum, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + pi = dx * sum; + + auto mpi_elapsed = MPI_Wtime() - mpi_t1; + second elapsed = clk::now() - t1; + + if(prank == 0) { + std::printf("computed pi = %.16g\n", pi); + std::printf("wall clock time (mpi_wtime) = %.4gs with %d process\n", mpi_elapsed, psize); + std::printf("wall clock time (chrono) = %.4gs\n", elapsed.count()); + + for(int d = 1; d <= 15; ++d) { + std::printf("%d", digit(pi, d)); + } + } + + MPI_Finalize(); + + return 0; +} diff --git a/Serie07/pi/pi_p2p_async_ring.cc b/Serie07/pi/pi_p2p_async_ring.cc new file mode 100644 index 0000000..ce042e8 --- /dev/null +++ b/Serie07/pi/pi_p2p_async_ring.cc @@ -0,0 +1,83 @@ +/* + This exercise is taken from the class Parallel Programming Workshop (MPI, + OpenMP and Advanced Topics) at HLRS given by Rolf Rabenseifner + */ + +#include +#include +#include +#include + +using clk = std::chrono::high_resolution_clock; +using second = std::chrono::duration; +using time_point = std::chrono::time_point; + +inline int digit(double x, int n) { + return std::trunc(x * std::pow(10., n)) - std::trunc(x * std::pow(10., n - 1)) *10.; +} + +inline double f(double a) { return (4. / (1. + a * a)); } + +const int n = 10000000; + +int main(int /* argc */ , char ** /* argv */) { + int i; + double dx, x, sum, pi; + int psize, prank; + + MPI_Init(NULL, NULL); + + MPI_Comm_size(MPI_COMM_WORLD, &psize); + MPI_Comm_rank(MPI_COMM_WORLD, &prank); + + auto mpi_t1 = MPI_Wtime(); + auto t1 = clk::now(); + + int nlocal = n / psize; + int istart = 1 + nlocal * prank; + int iend = nlocal * (prank + 1); + + /* calculate pi = integral [0..1] 4 / (1 + x**2) dx */ + dx = 1. / n; + sum = 0.0; + for (i = istart; i <= iend; i++) { + x = (1. * i - 0.5) * dx; + sum = sum + f(x); + } + + int next = (prank + 1) % psize; + int prev = (prank - 1 + psize) % psize; + + double send, recv; + MPI_Request request; + send = sum; + for(int s = 1; s < psize; ++s) { + MPI_Isend(&send, 1, MPI_DOUBLE, next, 13, MPI_COMM_WORLD, &request); + MPI_Recv(&recv, 1, MPI_DOUBLE, prev, 13, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + sum += recv; + + MPI_Wait(&request, MPI_STATUS_IGNORE); + + send = recv; + } + + pi = dx * sum; + + auto mpi_elapsed = MPI_Wtime() - mpi_t1; + second elapsed = clk::now() - t1; + + if(prank == 0) { + std::printf("computed pi = %.16g\n", pi); + std::printf("wall clock time (mpi_wtime) = %.4gs with %d process\n", mpi_elapsed, psize); + std::printf("wall clock time (chrono) = %.4gs\n", elapsed.count()); + + for(int d = 1; d <= 15; ++d) { + std::printf("%d", digit(pi, d)); + } + } + + MPI_Finalize(); + + return 0; +}