laplacien_mpi_2.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 nbNodes;
  11. MPI_Comm_size(MPI_COMM_WORLD, &nbNodes);
  12. int iNode;
  13. MPI_Comm_rank(MPI_COMM_WORLD, &iNode);
  14. if (iNode == 0) // master node
  15. {
  16. // read image
  17. image_t data0;
  18. int width, height;
  19. std::string readError = readPgm("backloop.pgm", width, height, data0);
  20. if (readError != "")
  21. {
  22. std::cout << readError << std::endl;
  23. exit(-1);
  24. }
  25. int heightN = (height+nbNodes-1) / nbNodes;
  26. int sizeN = heightN * width;
  27. int height2 = heightN * nbNodes;
  28. int size2 = height2 * width;
  29. // copy data0 in data1
  30. // ensure the height of data1 is a multiple of nbNodes
  31. image_t data1(size2);
  32. std::copy_n(data0.begin(), width*height, data1.begin());
  33. // send subimage sizes to slave nodes
  34. MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
  35. MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
  36. // send data to slave nodes
  37. image_t nodeData(sizeN);
  38. MPI_Scatter(data1.data(), sizeN, MPI_UNSIGNED_CHAR,
  39. nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
  40. 0, MPI_COMM_WORLD);
  41. // compute master data
  42. image_t nodeResult = computeLaplacian(nodeData, width, heightN, 10.0);
  43. // receive results from slave nodes
  44. image_t data2(size2, 0);
  45. MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
  46. data2.data(), sizeN, MPI_UNSIGNED_CHAR,
  47. 0, MPI_COMM_WORLD);
  48. // write output image
  49. writePgm("output_2.pgm", width, height, data2);
  50. std::cout << "walltime = " << MPI_Wtime() << std::endl;
  51. }
  52. else // slave nodes
  53. {
  54. // receive subimage sizes
  55. int width;
  56. MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
  57. int heightN;
  58. MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
  59. int sizeN = heightN * width;
  60. // receive data from master node
  61. image_t nodeData(sizeN);
  62. MPI_Scatter(nullptr, sizeN, MPI_UNSIGNED_CHAR,
  63. nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
  64. 0, MPI_COMM_WORLD);
  65. // compute node data
  66. image_t nodeResult = computeLaplacian(nodeData, width, heightN, 10.0);
  67. // send results to master node
  68. MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
  69. nullptr, sizeN, MPI_UNSIGNED_CHAR,
  70. 0, MPI_COMM_WORLD);
  71. }
  72. MPI_Finalize();
  73. return 0;
  74. }