codegod313

someMPI

Feb 24th, 2023 (edited)
699
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.98 KB | Cybersecurity | 0 0
  1. #include <iostream>
  2. #include <random>
  3. #include <mpi.h>
  4. #include <memory.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <chrono>
  8. #include <fstream>
  9.  
  10. #define PATH_TO_MATRICES "/home/mama/someMPI/ass/matrices.txt"
  11. #define PATH_TO_RESULT "/home/mama/someMPI/ass/res.txt"
  12.  
  13. double *multiplyMatrix(double *matrix1, double *matrix2, size_t n1, size_t m1, size_t n2, size_t m2)
  14. {
  15.     if (m1 != n2)
  16.     {
  17.         std::cout << "ERROR: matrices are incompatible" << std::endl;
  18.         exit(-1);
  19.     }
  20.     double *resMatrix = (double *)malloc(n1 * m2 * sizeof(double));
  21.     for (size_t i = 0; i < n1; i++)
  22.     {
  23.         for (size_t j = 0; j < m2; j++)
  24.         {
  25.             double element = 0;
  26.             for (size_t u = 0; u < m1; u++)
  27.             {
  28.                 element += matrix1[i * m1 + u] * matrix2[u * m2 + j];
  29.             }
  30.             resMatrix[i * m2 + j] = element;
  31.         }
  32.     }
  33.     return resMatrix;
  34. }
  35.  
  36. void matrixPrinter(double *matrix, size_t n, size_t m)
  37. {
  38.     for (size_t i = 0; i < n; i++)
  39.     {
  40.         for (size_t j = 0; j < m; j++)
  41.         {
  42.             std::cout << matrix[i * m + j] << " ";
  43.         }
  44.         std::cout << std::endl;
  45.     }
  46. }
  47.  
  48. void matrixRandomiser(double *matrix, size_t n, size_t m)
  49. {
  50.     for (size_t i = 0; i < n * m; i++)
  51.     {
  52.         matrix[i] = rand() % 100 + 1;
  53.     }
  54. }
  55.  
  56. void writeMatrixToFile(double *matrix, size_t n, size_t m, std::ofstream &file)
  57. {
  58.     file << n << " " << m << std::endl;
  59.     for (size_t i = 0; i < n; i++)
  60.     {
  61.         for (size_t j = 0; j < m; j++)
  62.         {
  63.             file << matrix[i * m + j] << " ";
  64.         }
  65.         file << std::endl;
  66.     }
  67. }
  68.  
  69. void createMatrixesAndWriteToFile(std::string path)
  70. {
  71.     std::ofstream fout;
  72.     fout.open(path);
  73.     std::cout << "Enter matrices dimensions" << std::endl;
  74.     size_t n1, m1, n2, m2;
  75.     std::cin >> n1 >> m1 >> n2 >> m2;
  76.     double *matrix1 = (double *)malloc(sizeof(double) * n1 * m1);
  77.     double *matrix2 = (double *)malloc(sizeof(double) * n2 * m2);
  78.     matrixRandomiser(matrix1, n1, m1);
  79.     matrixRandomiser(matrix2, n2, m2);
  80.     writeMatrixToFile(matrix1, n1, m1, fout);
  81.     writeMatrixToFile(matrix2, n2, m2, fout);
  82.     fout.close();
  83. }
  84.  
  85. void testMPI(int &argc, char *argv[])
  86. {
  87.  
  88.     int rank, number;
  89.     MPI_Init(&argc, &argv);
  90.  
  91.     MPI_Comm_size(MPI_COMM_WORLD, &number);
  92.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  93.     std::cout << "Rank: " << rank << "\nNumber of processes: " << number << std::endl;
  94.  
  95.     MPI_Finalize();
  96. }
  97.  
  98. double *readMatrixFromFile(std::ifstream &fin, size_t &n, size_t &m)
  99. {
  100.     fin >> n >> m;
  101.     double *matrix = (double *)malloc(sizeof(double) * n * m);
  102.     for (size_t i = 0; i < n * m; i++)
  103.     {
  104.         fin >> matrix[i];
  105.     }
  106.     return matrix;
  107. }
  108. void testMul()
  109. {
  110.     size_t n1, m1, n2, m2;
  111.     double *matrix1, *matrix2;
  112.     std::ifstream fin;
  113.     fin.open(PATH_TO_MATRICES);
  114.     matrix1 = readMatrixFromFile(fin, n1, m1);
  115.     matrix2 = readMatrixFromFile(fin, n2, m2);
  116.     fin.close();
  117.     auto start = std::chrono::high_resolution_clock::now();
  118.     double *res = multiplyMatrix(matrix1, matrix2, n1, m1, n2, m2);
  119.     auto stop = std::chrono::high_resolution_clock::now();
  120.     auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
  121.     std::cout << "Elapsed time (one process) " << duration.count() << " seconds" << std::endl;
  122. }
  123.  
  124. void processMatrixRoot(int numberOfProcesses)
  125. {
  126.     createMatrixesAndWriteToFile(PATH_TO_MATRICES);
  127.     size_t n1, m1, n2, m2;
  128.  
  129.     std::ifstream fin;
  130.     fin.open(PATH_TO_MATRICES);
  131.  
  132.     double *matrix1, *matrix2;
  133.  
  134.     matrix1 = readMatrixFromFile(fin, n1, m1);
  135.     matrix2 = readMatrixFromFile(fin, n2, m2);
  136.  
  137.     fin.close();
  138.  
  139.     if (m1 != n2)
  140.     {
  141.         std::cout << "ERROR: matrices are incompatible" << std::endl;
  142.         exit(-1);
  143.     }
  144.     std::cout << "OK" << std::endl;
  145.     // matrixPrinter(matrix1, n1, m1);
  146.     // matrixPrinter(matrix2, n2, m2);
  147.     // sleep(2);
  148.     size_t numberOfRowsForEachProcessFirstMatrix = n1 / (numberOfProcesses - 1);
  149.     size_t numberOfRowsForEachProcessSecondMatrix = n2 / (numberOfProcesses - 1);
  150.     auto start = std::chrono::high_resolution_clock::now();
  151.     for (int i = 1; i < numberOfProcesses; i++)
  152.     {
  153.         // std::cout << "Sending dimensions to " << i << " process" << std::endl;
  154.         MPI_Send(&n1, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD);
  155.         MPI_Send(&m1, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD);
  156.         MPI_Send(&n2, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD);
  157.         MPI_Send(&m2, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD);
  158.         // std::cout << "Dimensions sent" << std::endl;
  159.  
  160.         if (i == numberOfProcesses - 1 && n1 % (numberOfProcesses - 1) != 0)
  161.         {
  162.             // std::cout << "Sending ..." << std::endl;
  163.             // matrixPrinter(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, numberOfRowsForEachProcessFirstMatrix + 1, m1);
  164.             // sleep(2);
  165.             MPI_Send(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * (numberOfRowsForEachProcessFirstMatrix + 1), MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  166.             MPI_Send(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * numberOfRowsForEachProcessSecondMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  167.             continue;
  168.         }
  169.         if (i == numberOfProcesses - 1 && n2 % (numberOfProcesses - 1) != 0)
  170.         {
  171.             // std::cout << "Sending 2 ..." << std::endl;
  172.             // matrixPrinter(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, numberOfRowsForEachProcessSecondMatrix + 1, m2);
  173.             // sleep(2);
  174.             MPI_Send(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * numberOfRowsForEachProcessFirstMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  175.             MPI_Send(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * (numberOfRowsForEachProcessSecondMatrix + 1), MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  176.             continue;
  177.         }
  178.  
  179.         // std::cout << "Sending ..." << std::endl;
  180.         // matrixPrinter(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, numberOfRowsForEachProcessFirstMatrix, m1);
  181.         // sleep(2);
  182.  
  183.         // matrixPrinter(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, numberOfRowsForEachProcessSecondMatrix, m2);
  184.         // sleep(2);
  185.  
  186.         MPI_Send(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * numberOfRowsForEachProcessFirstMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  187.         MPI_Send(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * numberOfRowsForEachProcessSecondMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  188.     }
  189.     double *res = (double *)malloc(sizeof(double) * n1 * m2);
  190.     memset(res, 0, n1 * m2);
  191.     double *fakeRes = (double *)malloc(sizeof(double) * n1 * m2);
  192.     memset(fakeRes, 0, n1 * m2);
  193.     MPI_Reduce(fakeRes, res, n1 * m2, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
  194.     auto stop = std::chrono::high_resolution_clock::now();
  195.     auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
  196.     std::cout << "Elapsed time sync: " << duration.count() << " seconds " << std::endl;
  197.     std::ofstream fout;
  198.     fout.open(PATH_TO_RESULT);
  199.     writeMatrixToFile(res, n1, m2, fout);
  200.     fout.close();
  201. }
  202. void processMatrixRootAsync(int numberOfProcesses)
  203. {
  204.     size_t n1, m1, n2, m2;
  205.  
  206.     std::ifstream fin;
  207.     fin.open(PATH_TO_MATRICES);
  208.  
  209.     double *matrix1, *matrix2;
  210.  
  211.     matrix1 = readMatrixFromFile(fin, n1, m1);
  212.     matrix2 = readMatrixFromFile(fin, n2, m2);
  213.  
  214.     fin.close();
  215.  
  216.     if (m1 != n2)
  217.     {
  218.         std::cout << "ERROR: matrices are incompatible" << std::endl;
  219.         exit(-1);
  220.     }
  221.     std::cout << "OK" << std::endl;
  222.     // matrixPrinter(matrix1, n1, m1);
  223.     // matrixPrinter(matrix2, n2, m2);
  224.     // sleep(2);
  225.     size_t numberOfRowsForEachProcessFirstMatrix = n1 / (numberOfProcesses - 1);
  226.     size_t numberOfRowsForEachProcessSecondMatrix = n2 / (numberOfProcesses - 1);
  227.     MPI_Request request;
  228.     auto start = std::chrono::high_resolution_clock::now();
  229.     for (int i = 1; i < numberOfProcesses; i++)
  230.     {
  231.         // std::cout << "Sending dimensions to " << i << " process" << std::endl;
  232.         MPI_Isend(&n1, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD, &request);
  233.         MPI_Isend(&m1, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD, &request);
  234.         MPI_Isend(&n2, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD, &request);
  235.         MPI_Isend(&m2, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD, &request);
  236.         // std::cout << "Dimensions sent" << std::endl;
  237.  
  238.         if (i == numberOfProcesses - 1 && n1 % (numberOfProcesses - 1) != 0)
  239.         {
  240.             // std::cout << "Sending ..." << std::endl;
  241.             // matrixPrinter(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, numberOfRowsForEachProcessFirstMatrix + 1, m1);
  242.             // sleep(2);
  243.             MPI_Isend(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * (numberOfRowsForEachProcessFirstMatrix + 1), MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  244.             MPI_Isend(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * numberOfRowsForEachProcessSecondMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  245.             continue;
  246.         }
  247.         if (i == numberOfProcesses - 1 && n2 % (numberOfProcesses - 1) != 0)
  248.         {
  249.             // std::cout << "Sending 2 ..." << std::endl;
  250.             // matrixPrinter(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, numberOfRowsForEachProcessSecondMatrix + 1, m2);
  251.             // sleep(2);
  252.             MPI_Isend(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * numberOfRowsForEachProcessFirstMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  253.             MPI_Isend(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * (numberOfRowsForEachProcessSecondMatrix + 1), MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  254.             continue;
  255.         }
  256.  
  257.         // std::cout << "Sending ..." << std::endl;
  258.         // matrixPrinter(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, numberOfRowsForEachProcessFirstMatrix, m1);
  259.         // sleep(2);
  260.  
  261.         // matrixPrinter(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, numberOfRowsForEachProcessSecondMatrix, m2);
  262.         // sleep(2);
  263.  
  264.         MPI_Isend(matrix1 + (i - 1) * numberOfRowsForEachProcessFirstMatrix * m1, m1 * numberOfRowsForEachProcessFirstMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  265.         MPI_Isend(matrix2 + (i - 1) * numberOfRowsForEachProcessSecondMatrix * m2, m2 * numberOfRowsForEachProcessSecondMatrix, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
  266.     }
  267.     double *res = (double *)malloc(sizeof(double) * n1 * m2);
  268.     memset(res, 0, n1 * m2);
  269.     double *fakeRes = (double *)malloc(sizeof(double) * n1 * m2);
  270.     memset(fakeRes, 0, n1 * m2);
  271.     MPI_Reduce(fakeRes, res, n1 * m2, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
  272.     auto stop = std::chrono::high_resolution_clock::now();
  273.     auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
  274.     std::cout << "Elapsed time async: " << duration.count() << " seconds " << std::endl;
  275.     std::ofstream fout;
  276.     fout.open(PATH_TO_RESULT);
  277.     writeMatrixToFile(res, n1, m2, fout);
  278.     fout.close();
  279. }
  280.  
  281. void processMatrixSlave(int numberOfProcesses, int rank)
  282. {
  283.     rank--;
  284.     // std::cout << "This is slave process\n Waiting for info...\n";
  285.  
  286.     size_t n1, m1, n2, m2;
  287.     MPI_Status status;
  288.     MPI_Recv(&n1, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD, &status);
  289.     MPI_Recv(&m1, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD, &status);
  290.     MPI_Recv(&n2, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD, &status);
  291.     MPI_Recv(&m2, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD, &status);
  292.  
  293.     // std::cout << "Dimensions received!\n";
  294.     int numberOfLinesFirstMatrix = n1 / (numberOfProcesses - 1);
  295.     int numberOfLinesSecondMatrix = n2 / (numberOfProcesses - 1);
  296.  
  297.     int firstLineFirstMatrix = rank * numberOfLinesFirstMatrix;
  298.     int firstLineSecondMatrix = rank * numberOfLinesSecondMatrix;
  299.  
  300.     // std::cout << "First line for rank " << rank << " is" << firstLineFirstMatrix << std::endl;
  301.     // std::cout << "First line for sm rank " << rank << " is" << firstLineSecondMatrix << std::endl;
  302.  
  303.     if (rank == numberOfProcesses - 2 && n1 % (numberOfProcesses - 1) != 0)
  304.     {
  305.         numberOfLinesFirstMatrix++;
  306.     }
  307.     if (rank == numberOfProcesses - 2 && n2 % (numberOfProcesses - 1) != 0)
  308.     {
  309.         //std::cout << "Boooo " << numberOfLinesSecondMatrix << std::endl;
  310.         numberOfLinesSecondMatrix++;
  311.     }
  312.  
  313.     double *res = (double *)malloc(sizeof(double) * n1 * m2);
  314.     memset(res, 0, sizeof(double) * n1 * m2);
  315.  
  316.     double *matrix1 = (double *)malloc(sizeof(double) * m1 * numberOfLinesFirstMatrix);
  317.     double *matrix2 = (double *)malloc(sizeof(double) * m2 * numberOfLinesSecondMatrix);
  318.  
  319.     MPI_Recv(matrix1, m1 * numberOfLinesFirstMatrix, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
  320.     MPI_Recv(matrix2, m2 * numberOfLinesSecondMatrix, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
  321.  
  322.     // std::cout << "Everything is received!" << std::endl;
  323.     // if (rank == 2)
  324.     // {
  325.     //     sleep(1);
  326.     //     std::cout << "Received matrix 1:" << std::endl;
  327.     //     matrixPrinter(matrix1, numberOfLinesFirstMatrix, m1);
  328.     //     std::cout << "Received matrix 2:" << std::endl;
  329.     //     matrixPrinter(matrix2, numberOfLinesSecondMatrix, m2);
  330.     // }
  331.     for (int u = 0; u < numberOfProcesses - 1; u++)
  332.     {
  333.         for (size_t k = 0; k < m2; k++)
  334.         {
  335.             for (int i = firstLineFirstMatrix; i < firstLineFirstMatrix + numberOfLinesFirstMatrix; i++)
  336.             {
  337.                 for (int j = firstLineSecondMatrix; j < firstLineSecondMatrix + numberOfLinesSecondMatrix; j++)
  338.                 {
  339.                     // if (rank == 2)
  340.                     // {
  341.                     //     sleep(2);
  342.                     //     std::cout << i << " " << j << " - " << matrix1[(i - firstLineFirstMatrix) * m1 + j] << " " << matrix2[(j - firstLineSecondMatrix) * m2 + k] << std::endl;
  343.                     //     std::cout << "Added to " << i << " " << k << std::endl;
  344.                     // }
  345.                     res[i * m2 + k] += matrix1[(i - firstLineFirstMatrix) * m1 + j] * matrix2[(j - firstLineSecondMatrix) * m2 + k];
  346.                     // if (rank == 2)
  347.                     // {
  348.                     //     matrixPrinter(res, n1, m2);
  349.                     // }
  350.                 }
  351.             }
  352.         }
  353.         int dst = rank + 2;
  354.         if (dst >= numberOfProcesses)
  355.             dst = 1;
  356.         int src = rank;
  357.         if (rank == 0)
  358.             src = numberOfProcesses - 1;
  359.         int numberOfLinesTMP = numberOfLinesSecondMatrix;
  360.         MPI_Sendrecv_replace(&numberOfLinesSecondMatrix, 1, MPI_INT, dst, 0, src, 0, MPI_COMM_WORLD, &status);
  361.         MPI_Sendrecv_replace(&firstLineSecondMatrix, 1, MPI_INT, dst, 0, src, 0, MPI_COMM_WORLD, &status);
  362.  
  363.         double *matrix2N = (double *)malloc(sizeof(double) * numberOfLinesSecondMatrix * m2);
  364.         MPI_Sendrecv(matrix2, numberOfLinesTMP * m2, MPI_DOUBLE, dst, 0, matrix2N, numberOfLinesSecondMatrix * m2, MPI_DOUBLE, src, 0, MPI_COMM_WORLD, &status);
  365.         free(matrix2);
  366.         matrix2 = matrix2N;
  367.         // if (rank == 2)
  368.         // {
  369.         //     std::cout << "FLSM " << firstLineSecondMatrix << std::endl;
  370.         //     std::cout << "Received matrix" << std::endl;
  371.         //     matrixPrinter(matrix2N, numberOfLinesSecondMatrix, m2);
  372.         //     sleep(2);
  373.         // }
  374.     }
  375.     // sleep(rank);
  376.     // std::cout << n1 << " " << m2 << std::endl;
  377.  
  378.     MPI_Reduce(res, NULL, n1 * m2, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
  379.     // matrixPrinter(res, n1, m2);
  380. }
  381.  
  382. void testP2P2SynchronousMatrixMul(int &argc, char *argv[])
  383. {
  384.  
  385.     int rank, numberOfProcesses;
  386.     MPI_Init(&argc, &argv);
  387.  
  388.     MPI_Comm_size(MPI_COMM_WORLD, &numberOfProcesses);
  389.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  390.     // std::cout << "Rank: " << rank << "\nNumber of processes: " << numberOfProcesses << std::endl;
  391.  
  392.     if (rank == 0)
  393.     {
  394.         processMatrixRoot(numberOfProcesses);
  395.         testMul();
  396.     }
  397.     else
  398.     {
  399.         processMatrixSlave(numberOfProcesses, rank);
  400.     }
  401.     MPI_Barrier(MPI_COMM_WORLD);
  402. }
  403.  
  404. void testP2P2AsynchronousMatrixMul(int &argc, char *argv[])
  405. {
  406.  
  407.     int rank, numberOfProcesses;
  408.  
  409.     MPI_Comm_size(MPI_COMM_WORLD, &numberOfProcesses);
  410.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  411.     // std::cout << "Rank: " << rank << "\nNumber of processes: " << numberOfProcesses << std::endl;
  412.  
  413.     if (rank == 0)
  414.     {
  415.         processMatrixRootAsync(numberOfProcesses);
  416.         // testMul();
  417.     }
  418.     else
  419.     {
  420.         processMatrixSlave(numberOfProcesses, rank);
  421.     }
  422.  
  423.     MPI_Finalize();
  424. }
  425.  
  426. void test7Lab(int argc, char *argv[])
  427. {
  428.     testP2P2SynchronousMatrixMul(argc, argv);
  429.     testP2P2AsynchronousMatrixMul(argc, argv);
  430. }
  431.  
  432. int main(int argc, char *argv[])
  433. {
  434.     test7Lab(argc, argv);
  435. }
  436.  
Advertisement
Add Comment
Please, Sign In to add comment