laplacien_mpi_2.cpp 3.3 KB

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