diff --git a/Serie05/pi/solutions/Makefile b/Serie05/pi/solutions/Makefile new file mode 100644 index 0000000..9ff0caf --- /dev/null +++ b/Serie05/pi/solutions/Makefile @@ -0,0 +1,14 @@ +OPTIM+=-O3 + +CXX=mpicxx +CC=mpicxx +LD=${CXX} +CXXFLAGS+=-Wall -Wextra -std=c++11 $(OPTIM) +LDFLAGS+=$(OPTIM) -lm + +EXECS=pi pi_p2p_ring + +all: clean $(EXECS) + +clean: + rm -f $(EXECS) *.o *~ diff --git a/Serie05/pi/solutions/pi.cc b/Serie05/pi/solutions/pi.cc new file mode 100644 index 0000000..18d9f10 --- /dev/null +++ b/Serie05/pi/solutions/pi.cc @@ -0,0 +1,63 @@ +/* + 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(); + + /* calculate pi = integral [0..1] 4 / (1 + x**2) dx */ + dx = 1. / n; + sum = 0.0; + for (i = 1; i <= n; i++) { + x = (1. * i - 0.5) * dx; + sum = sum + f(x); + } + 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/Serie05/pi/solutions/pi_gather.cc b/Serie05/pi/solutions/pi_gather.cc new file mode 100644 index 0000000..978c4a4 --- /dev/null +++ b/Serie05/pi/solutions/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/Serie05/pi/solutions/pi_p2p_async_ring.cc b/Serie05/pi/solutions/pi_p2p_async_ring.cc new file mode 100644 index 0000000..ce042e8 --- /dev/null +++ b/Serie05/pi/solutions/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; +} diff --git a/Serie05/pi/solutions/pi_p2p_ring b/Serie05/pi/solutions/pi_p2p_ring new file mode 100755 index 0000000..c1e6645 Binary files /dev/null and b/Serie05/pi/solutions/pi_p2p_ring differ diff --git a/Serie05/pi/solutions/pi_p2p_ring.cc b/Serie05/pi/solutions/pi_p2p_ring.cc new file mode 100644 index 0000000..fa59690 --- /dev/null +++ b/Serie05/pi/solutions/pi_p2p_ring.cc @@ -0,0 +1,84 @@ +/* + 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; + send = sum; + for(int s = 1; s < psize; ++s) { + if(prank % 2 == 0) { + MPI_Ssend(&send, 1, MPI_DOUBLE, next, 13, MPI_COMM_WORLD); + MPI_Recv(&recv, 1, MPI_DOUBLE, prev, 13, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } else { + MPI_Recv(&recv, 1, MPI_DOUBLE, prev, 13, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + MPI_Ssend(&send, 1, MPI_DOUBLE, next, 13, MPI_COMM_WORLD); + } + + sum += recv; + 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; +} diff --git a/Serie05/pi/solutions/pi_p2p_sendrecv_ring.cc b/Serie05/pi/solutions/pi_p2p_sendrecv_ring.cc new file mode 100644 index 0000000..932197e --- /dev/null +++ b/Serie05/pi/solutions/pi_p2p_sendrecv_ring.cc @@ -0,0 +1,80 @@ +/* + 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; + send = sum; + for(int s = 1; s < psize; ++s) { + MPI_Sendrecv(&send, 1, MPI_DOUBLE, next, 13, + &recv, 1, MPI_DOUBLE, prev, 13, + MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + sum += recv; + 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; +} diff --git a/Serie05/pi/solutions/pi_reduce.cc b/Serie05/pi/solutions/pi_reduce.cc new file mode 100644 index 0000000..7799f8f --- /dev/null +++ b/Serie05/pi/solutions/pi_reduce.cc @@ -0,0 +1,68 @@ +/* + 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); + } + + MPI_Allreduce(MPI_IN_PLACE, &sum, 1, MPI_DOUBLE, MPI_SUM, 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; +}