123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // mpic++ -std=c++11 -Wall -Wextra -o laplacien_mpi_2.out laplacien_mpi_2.cpp
- // mpirun -n 4 ./laplacien_mpi_2.out canyon.pgm canyon_mpi_2.pgm
- // separate master code and slave code
- #include "image.hpp"
- #include <algorithm>
- #include <mpi.h>
- int main(int argc, char ** argv)
- {
- // init MPI
- MPI_Init(&argc, &argv);
- int worldSize;
- MPI_Comm_size(MPI_COMM_WORLD, &worldSize);
- int worldRank;
- MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
- if (argc != 5)
- {
- std::cout << "usage: " << argv[0]
- << " <input> <output> <scaling> <nb fakes>\n";
- exit(-1);
- }
- const char * INPUT = argv[1];
- const char * OUTPUT = argv[2];
- const float SCALING = atof(argv[3]);
- const int NB_FAKES = atoi(argv[4]);
- if (worldRank == 0) // master node
- {
- double t0 = MPI_Wtime();
- // read image
- image_t data0;
- int width, height;
- std::string readError = readPgm(INPUT, width, height, data0);
- if (readError != "")
- {
- std::cout << readError << std::endl;
- exit(-1);
- }
- int heightN = (height+worldSize-1) / worldSize;
- int sizeN = heightN * width;
- int height2 = heightN * worldSize;
- int size2 = height2 * width;
- // copy data0 in data1
- // ensure the height of data1 is a multiple of worldSiz
- image_t data1(size2);
- std::copy_n(data0.begin(), width*height, data1.begin());
- // send subimage sizes to slave nodes
- MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
- MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
- // send data to slave nodes
- image_t nodeData(sizeN);
- MPI_Scatter(data1.data(), sizeN, MPI_UNSIGNED_CHAR,
- nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
- 0, MPI_COMM_WORLD);
- // compute master data
- image_t nodeResult = computeLaplacian(nodeData, width, heightN, SCALING);
- for (int k=0; k<NB_FAKES; ++k)
- nodeResult = computeLaplacian(nodeData, width, heightN, SCALING);
- // receive results from slave nodes
- image_t data2(size2, 0);
- MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
- data2.data(), sizeN, MPI_UNSIGNED_CHAR,
- 0, MPI_COMM_WORLD);
- // write output image
- writePgm(OUTPUT, width, height, data2);
- double t1 = MPI_Wtime();
- std::cout << t1 - t0;
- }
- else // slave nodes
- {
- // receive subimage sizes
- int width;
- MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
- int heightN;
- MPI_Bcast(&heightN, 1, MPI_INT, 0, MPI_COMM_WORLD);
- int sizeN = heightN * width;
- // receive data from master node
- image_t nodeData(sizeN);
- MPI_Scatter(nullptr, sizeN, MPI_UNSIGNED_CHAR,
- nodeData.data(), sizeN, MPI_UNSIGNED_CHAR,
- 0, MPI_COMM_WORLD);
- // compute node data
- image_t nodeResult = computeLaplacian(nodeData, width, heightN, SCALING);
- for (int k=0; k<NB_FAKES; ++k)
- nodeResult = computeLaplacian(nodeData, width, heightN, SCALING);
- // send results to master node
- MPI_Gather(nodeResult.data(), sizeN, MPI_UNSIGNED_CHAR,
- nullptr, sizeN, MPI_UNSIGNED_CHAR,
- 0, MPI_COMM_WORLD);
- }
- MPI_Finalize();
- return 0;
- }
|