laplacien_mpi_2.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // mpic++ -std=c++11 -Wall -Wextra -o laplacien_mpi_2.out laplacien_mpi_2.cpp
  2. // mpirun -n 4 ./laplacien_mpi_2.out
  3. #include "image.hpp"
  4. #include <algorithm>
  5. #include <mpi.h>
  6. int main(int argc, char ** argv)
  7. {
  8. // init MPI
  9. MPI_Init(&argc, &argv);
  10. int worldSize;
  11. MPI_Comm_size(MPI_COMM_WORLD, &worldSize);
  12. int worldRank;
  13. MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
  14. if (worldRank == 0) // master node
  15. {
  16. double t0 = MPI_Wtime();
  17. // read image
  18. image_t data0;
  19. int width, height;
  20. std::string readError = readPgm("backloop.pgm", width, height, data0);
  21. if (readError != "")
  22. {
  23. std::cout << readError << std::endl;
  24. exit(-1);
  25. }
  26. int heightN = (height+worldSize-1) / worldSize;
  27. int sizeN = heightN * width;
  28. int height2 = heightN * worldSize;
  29. int size2 = height2 * width;
  30. // copy data0 in data1
  31. // ensure the height of data1 is a multiple of worldSiz
  32. image_t data1(size2);
  33. std::copy_n(data0.begin(), width*height, data1.begin());
  34. // send subimage sizes to slave nodes
  35. MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
  36. MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
  37. // send data to slave nodes
  38. image_t nodeData(sizeN);
  39. MPI_Scatter(data1.data(), sizeN, MPI_UNSIGNED_CHAR,
  40. nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
  41. 0, MPI_COMM_WORLD);
  42. // compute master data
  43. image_t nodeResult = computeLaplacian(nodeData, width, heightN, 10.0);
  44. // receive results from slave nodes
  45. image_t data2(size2, 0);
  46. MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
  47. data2.data(), sizeN, MPI_UNSIGNED_CHAR,
  48. 0, MPI_COMM_WORLD);
  49. // write output image
  50. writePgm("output_2.pgm", width, height, data2);
  51. double t1 = MPI_Wtime();
  52. std::cout << "walltime = " << t1 - t0 << std::endl;
  53. }
  54. else // slave nodes
  55. {
  56. // receive subimage sizes
  57. int width;
  58. MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
  59. int heightN;
  60. MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
  61. int sizeN = heightN * width;
  62. // receive data from master node
  63. image_t nodeData(sizeN);
  64. MPI_Scatter(nullptr, sizeN, MPI_UNSIGNED_CHAR,
  65. nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
  66. 0, MPI_COMM_WORLD);
  67. // compute node data
  68. image_t nodeResult = computeLaplacian(nodeData, width, heightN, 10.0);
  69. // send results to master node
  70. MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
  71. nullptr, sizeN, MPI_UNSIGNED_CHAR,
  72. 0, MPI_COMM_WORLD);
  73. }
  74. MPI_Finalize();
  75. return 0;
  76. }