osipyonok

mpi mat mult

Mar 29th, 2017
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.38 KB | None | 0 0
  1. // ParallelPI.cpp: определяет точку входа для консольного приложения.
  2. //
  3.  
  4. #include "stdafx.h"
  5.  
  6. #include <bits\stdc++.h>
  7.  
  8. // Program code 7.1 Release 1.3 on 30.08.2006
  9. // Matrix-Vector Multiplication – rowwise block-striped decomposition
  10. // (the source and the result vectors are doubled amoung the processors)
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <conio.h>
  15. #include <time.h>
  16. #include <mpi.h>
  17.  
  18. int ProcNum = 0;      // Number of available processes
  19. int ProcRank = 0;     // Rank of current process
  20.  
  21. // Function for simple definition of matrix and vector elements
  22. void DummyDataInitialization (double* pMatrix, double* pVector, int Size) {
  23.   int i, j;  // Loop variables
  24.  
  25.   for (i=0; i<Size; i++) {
  26.     pVector[i] = 1;
  27.     for (j=0; j<Size; j++)
  28.       pMatrix[i*Size+j] = i;
  29.   }
  30. }
  31.  
  32. // Function for random definition of matrix and vector elements
  33. void RandomDataInitialization(double* pMatrix, double* pVector, int Size) {
  34.   int i, j;  // Loop variables
  35.   srand(unsigned(clock()));
  36.   for (i=0; i<Size; i++) {
  37.     pVector[i] = rand()/double(1000);
  38.     for (j=0; j<Size; j++)
  39.       pMatrix[i*Size+j] = rand()/double(1000);
  40.   }
  41. }
  42.  
  43. // Function for memory allocation and data initialization
  44. void ProcessInitialization (double* &pMatrix, double* &pVector,
  45.   double* &pResult, double* &pProcRows, double* &pProcResult,
  46.   int &Size, int &RowNum) {
  47.   int RestRows; // Number of rows, that haven’t been distributed yet
  48.   int i;        // Loop variable
  49.  
  50.   setvbuf(stdout, 0, _IONBF, 0);
  51.   if (ProcRank == 0) {
  52.     do {
  53.       printf("\nEnter size of the initial objects: ");
  54.       scanf("%d", &Size);
  55.       if (Size < ProcNum) {
  56.         printf("Size of the objects must be greater than number of processes!");
  57.       }
  58.     }
  59.     while (Size < ProcNum);
  60.   }
  61.   MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);
  62.  
  63.   // Determine the number of matrix rows stored on each process
  64.   RestRows = Size;
  65.   for (i=0; i<ProcRank; i++)
  66.     RestRows = RestRows-RestRows/(ProcNum-i);
  67.   RowNum = RestRows/(ProcNum-ProcRank);
  68.  
  69.   // Memory allocation
  70.   pVector = new double [Size];
  71.   pResult = new double [Size];
  72.   pProcRows = new double [RowNum*Size];
  73.   pProcResult = new double [RowNum];
  74.  
  75.   // Obtain the values of initial objects elements
  76.   if (ProcRank == 0) {
  77.     // Initial matrix exists only on the pivot process
  78.     pMatrix = new double [Size*Size];
  79.     // Values of elements are defined only on the pivot process
  80.     RandomDataInitialization(pMatrix, pVector, Size);
  81.   }
  82. }
  83.  
  84. // Function for distribution of the initial objects between the processes
  85. void DataDistribution(double* pMatrix, double* pProcRows, double* pVector,
  86.                       int Size, int RowNum) {
  87.   int *pSendNum;     // The number of elements sent to the process
  88.   int *pSendInd;     // The index of the first data element sent to the process
  89.   int RestRows=Size; // Number of rows, that haven’t been distributed yet
  90.  
  91.   MPI_Bcast(pVector, Size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  92.  
  93.   // Alloc memory for temporary objects
  94.   pSendInd = new int [ProcNum];
  95.   pSendNum = new int [ProcNum];
  96.  
  97.   // Define the disposition of the matrix rows for current process
  98.   RowNum = (Size/ProcNum);
  99.   pSendNum[0] = RowNum*Size;
  100.   pSendInd[0] = 0;
  101.   for (int i=1; i<ProcNum; i++) {
  102.     RestRows -= RowNum;
  103.     RowNum = RestRows/(ProcNum-i);
  104.     pSendNum[i] = RowNum*Size;
  105.     pSendInd[i] = pSendInd[i-1]+pSendNum[i-1];
  106.   }
  107.  
  108.   // Scatter the rows
  109.   MPI_Scatterv(pMatrix , pSendNum, pSendInd, MPI_DOUBLE, pProcRows,
  110.     pSendNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);
  111.  
  112.   // Free the memory
  113.   delete [] pSendNum;
  114.   delete [] pSendInd;                
  115. }
  116.  
  117. // Result vector replication
  118. void ResultReplication(double* pProcResult, double* pResult, int Size,
  119.     int RowNum) {
  120.   int i;             // Loop variable
  121.   int *pReceiveNum;  // Number of elements, that current process sends
  122.   int *pReceiveInd;  /* Index of the first element from current process
  123.                         in result vector */
  124.   int RestRows=Size; // Number of rows, that haven’t been distributed yet
  125.  
  126.   //Alloc memory for temporary objects
  127.   pReceiveNum = new int [ProcNum];
  128.   pReceiveInd = new int [ProcNum];
  129.  
  130.   //Define the disposition of the result vector block of current processor
  131.   pReceiveInd[0] = 0;
  132.   pReceiveNum[0] = Size/ProcNum;
  133.   for (i=1; i<ProcNum; i++) {
  134.     RestRows -= pReceiveNum[i-1];
  135.     pReceiveNum[i] = RestRows/(ProcNum-i);
  136.     pReceiveInd[i] = pReceiveInd[i-1]+pReceiveNum[i-1];
  137.   }
  138.  
  139.   //Gather the whole result vector on every processor
  140.   MPI_Allgatherv(pProcResult, pReceiveNum[ProcRank], MPI_DOUBLE, pResult,
  141.     pReceiveNum, pReceiveInd, MPI_DOUBLE, MPI_COMM_WORLD);
  142.  
  143.   //Free the memory
  144.   delete [] pReceiveNum;
  145.   delete [] pReceiveInd;
  146. }
  147.  
  148. // Function for sequential matrix-vector multiplication
  149. void SerialResultCalculation(double* pMatrix, double* pVector, double* pResult, int Size) {
  150.   int i, j;  // Loop variables
  151.   for (i=0; i<Size; i++) {
  152.     pResult[i] = 0;
  153.     for (j=0; j<Size; j++)
  154.       pResult[i] += pMatrix[i*Size+j]*pVector[j];
  155.   }
  156. }
  157.  
  158. // Process rows and vector multiplication
  159. void ParallelResultCalculation(double* pProcRows, double* pVector, double* pProcResult, int Size, int RowNum) {
  160.   int i, j;  // Loop variables
  161.   for (i=0; i<RowNum; i++) {
  162.     pProcResult[i] = 0;
  163.     for (j=0; j<Size; j++)
  164.       pProcResult[i] += pProcRows[i*Size+j]*pVector[j];
  165.   }
  166. }
  167.  
  168. // Function for formatted matrix output
  169. void PrintMatrix (double* pMatrix, int RowCount, int ColCount) {
  170.   int i, j; // Loop variables
  171.   for (i=0; i<RowCount; i++) {
  172.     for (j=0; j<ColCount; j++)
  173.       printf("%7.4f ", pMatrix[i*ColCount+j]);
  174.     printf("\n");
  175.   }
  176. }
  177.  
  178. // Function for formatted vector output
  179. void PrintVector (double* pVector, int Size) {
  180.   int i;
  181.   for (i=0; i<Size; i++)
  182.     printf("%7.4f ", pVector[i]);
  183. }
  184.  
  185. void TestDistribution(double* pMatrix, double* pVector, double* pProcRows,
  186.     int Size, int RowNum) {
  187.   if (ProcRank == 0) {
  188.     printf("Initial Matrix: \n");
  189.     PrintMatrix(pMatrix, Size, Size);
  190.     printf("Initial Vector: \n");
  191.     PrintVector(pVector, Size);
  192.   }
  193.   MPI_Barrier(MPI_COMM_WORLD);
  194.   for (int i=0; i<ProcNum; i++) {
  195.     if (ProcRank == i) {
  196.       printf("\nProcRank = %d \n", ProcRank);
  197.       printf(" Matrix Stripe:\n");
  198.       PrintMatrix(pProcRows, RowNum, Size);
  199.       printf(" Vector: \n");
  200.       PrintVector(pVector, Size);
  201.     }
  202.     MPI_Barrier(MPI_COMM_WORLD);
  203.   }
  204. }
  205.  
  206. // Fuction for testing the results of multiplication of the matrix stripe
  207. // by a vector
  208. void TestPartialResults(double* pProcResult, int RowNum) {
  209.   int i;    // Loop variables
  210.   for (i=0; i<ProcNum; i++) {
  211.     if (ProcRank == i) {
  212.       printf("\nProcRank = %d \n Part of result vector: \n", ProcRank);
  213.       PrintVector(pProcResult, RowNum);
  214.     }
  215.     MPI_Barrier(MPI_COMM_WORLD);
  216.   }
  217. }
  218.  
  219. // Testing the result of parallel matrix-vector multiplication
  220. void TestResult(double* pMatrix, double* pVector, double* pResult,
  221.   int Size) {
  222.   // Buffer for storing the result of serial matrix-vector multiplication
  223.   double* pSerialResult;
  224.   // Flag, that shows wheather the vectors are identical or not
  225.   int equal = 0;        
  226.   int i;                 // Loop variable
  227.  
  228.   if (ProcRank == 0) {
  229.     pSerialResult = new double [Size];
  230.     SerialResultCalculation(pMatrix, pVector, pSerialResult, Size);
  231.     for (i=0; i<Size; i++) {
  232.       if (pResult[i] != pSerialResult[i])
  233.         equal = 1;
  234.     }
  235.     if (equal == 1)
  236.       printf("The results of serial and parallel algorithms are NOT identical."
  237.              "Check your code.");
  238.     else
  239.       printf("The results of serial and parallel algorithms are identical.");
  240.   }
  241. }
  242.  
  243. // Function for computational process termination
  244. void ProcessTermination (double* pMatrix, double* pVector, double* pResult,
  245.     double* pProcRows, double* pProcResult) {
  246.   if (ProcRank == 0)
  247.     delete [] pMatrix;
  248.   delete [] pVector;
  249.   delete [] pResult;
  250.   delete [] pProcRows;
  251.   delete [] pProcResult;
  252. }
  253.  
  254. int main(int argc, char* argv[]){
  255.   double* pMatrix;      // The first argument - initial matrix
  256.   double* pVector;      // The second argument - initial vector
  257.   double* pResult;      // Result vector for matrix-vector multiplication
  258.   int Size;           // Sizes of initial matrix and vector
  259.   double* pProcRows;    // Stripe of the matrix on the current process
  260.   double* pProcResult;  // Block of the result vector on the current process
  261.   int RowNum;           // Number of rows in the matrix stripe
  262.  
  263.   MPI_Init(&argc, &argv);
  264.   MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
  265.   MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
  266.  
  267.   if (ProcRank == 0) {
  268.     printf ("Parallel matrix-vector multiplication program\n");
  269.   }
  270.  
  271.   // Memory allocation and data initialization
  272.   ProcessInitialization(pMatrix, pVector, pResult, pProcRows, pProcResult,  Size, RowNum);
  273.  
  274.   // Distributing the initial objects between the processes
  275.   DataDistribution(pMatrix, pProcRows, pVector, Size, RowNum);
  276.  
  277.   // Process rows and vector multiplication
  278.   ParallelResultCalculation(pProcRows, pVector, pProcResult, Size, RowNum);
  279.  
  280.   // Result replication
  281.   ResultReplication(pProcResult, pResult, Size, RowNum);
  282.  
  283.  
  284.   TestResult(pMatrix, pVector, pResult, Size);
  285.  
  286.   // Process termination
  287.   ProcessTermination(pMatrix, pVector, pResult, pProcRows, pProcResult);
  288.  
  289.   MPI_Finalize();
  290.   system("pause");
  291.   return 0;
  292. }
Add Comment
Please, Sign In to add comment