Advertisement
Guest User

Untitled

a guest
Feb 28th, 2017
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.42 KB | None | 0 0
  1. /**********************************************************************************************
  2. * Matrix Multiplication Program using MPI.
  3. *
  4. * Viraj Brian Wijesuriya - University of Colombo School of Computing, Sri Lanka.
  5. *
  6. * Works with any type of two matrixes [A], [B] which could be multiplied to produce a matrix [c].
  7. *
  8. * Master process initializes the multiplication operands, distributes the muliplication
  9. * operation to worker processes and reduces the worker results to construct the final output.
  10. *
  11. ************************************************************************************************/
  12. #include<stdio.h>
  13. #include<mpi.h>
  14. #define NUM_ROWS_A 12 //rows of input [A]
  15. #define NUM_COLUMNS_A 12 //columns of input [A]
  16. #define NUM_ROWS_B 12 //rows of input [B]
  17. #define NUM_COLUMNS_B 12 //columns of input [B]
  18. #define MASTER_TO_SLAVE_TAG 1 //tag for messages sent from master to slaves
  19. #define SLAVE_TO_MASTER_TAG 4 //tag for messages sent from slaves to master
  20. void makeAB(); //makes the [A] and [B] matrixes
  21. void printArray(); //print the content of output matrix [C];
  22. int rank; //process rank
  23. int size; //number of processes
  24. int i, j, k; //helper variables
  25. double mat_a[NUM_ROWS_A][NUM_COLUMNS_A]; //declare input [A]
  26. double mat_b[NUM_ROWS_B][NUM_COLUMNS_B]; //declare input [B]
  27. double mat_result[NUM_ROWS_A][NUM_COLUMNS_B]; //declare output [C]
  28. double start_time; //hold start time
  29. double end_time; // hold end time
  30. int low_bound; //low bound of the number of rows of [A] allocated to a slave
  31. int upper_bound; //upper bound of the number of rows of [A] allocated to a slave
  32. int portion; //portion of the number of rows of [A] allocated to a slave
  33. MPI_Status status; // store status of a MPI_Recv
  34. MPI_Request request; //capture request of a MPI_Isend
  35. int main(int argc, char *argv[])
  36. {
  37. MPI_Init(&argc, &argv); //initialize MPI operations
  38. MPI_Comm_rank(MPI_COMM_WORLD, &rank); //get the rank
  39. MPI_Comm_size(MPI_COMM_WORLD, &size); //get number of processes
  40. /* master initializes work*/
  41. if (rank == 0) {
  42. makeAB();
  43. start_time = MPI_Wtime();
  44. for (i = 1; i < size; i++) {//for each slave other than the master
  45. portion = (NUM_ROWS_A / (size - 1)); // calculate portion without master
  46. low_bound = (i - 1) * portion;
  47. if (((i + 1) == size) && ((NUM_ROWS_A % (size - 1)) != 0)) {//if rows of [A] cannot be equally divided among slaves
  48. upper_bound = NUM_ROWS_A; //last slave gets all the remaining rows
  49. } else {
  50. upper_bound = low_bound + portion; //rows of [A] are equally divisable among slaves
  51. }
  52. //send the low bound first without blocking, to the intended slave
  53. MPI_Isend(&low_bound, 1, MPI_INT, i, MASTER_TO_SLAVE_TAG, MPI_COMM_WORLD, &request);
  54. //next send the upper bound without blocking, to the intended slave
  55. MPI_Isend(&upper_bound, 1, MPI_INT, i, MASTER_TO_SLAVE_TAG + 1, MPI_COMM_WORLD, &request);
  56. //finally send the allocated row portion of [A] without blocking, to the intended slave
  57. MPI_Isend(&mat_a[low_bound][0], (upper_bound - low_bound) * NUM_COLUMNS_A, MPI_DOUBLE, i, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &request);
  58. }
  59. }
  60. //broadcast [B] to all the slaves
  61. MPI_Bcast(&mat_b, NUM_ROWS_B*NUM_COLUMNS_B, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  62. /* work done by slaves*/
  63. if (rank > 0) {
  64. //receive low bound from the master
  65. MPI_Recv(&low_bound, 1, MPI_INT, 0, MASTER_TO_SLAVE_TAG, MPI_COMM_WORLD, &status);
  66. //next receive upper bound from the master
  67. MPI_Recv(&upper_bound, 1, MPI_INT, 0, MASTER_TO_SLAVE_TAG + 1, MPI_COMM_WORLD, &status);
  68. //finally receive row portion of [A] to be processed from the master
  69. MPI_Recv(&mat_a[low_bound][0], (upper_bound - low_bound) * NUM_COLUMNS_A, MPI_DOUBLE, 0, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &status);
  70. for (i = low_bound; i < upper_bound; i++) {//iterate through a given set of rows of [A]
  71. for (j = 0; j < NUM_COLUMNS_B; j++) {//iterate through columns of [B]
  72. for (k = 0; k < NUM_ROWS_B; k++) {//iterate through rows of [B]
  73. mat_result[i][j] += (mat_a[i][k] * mat_b[k][j]);
  74. }
  75. }
  76. }
  77. //send back the low bound first without blocking, to the master
  78. MPI_Isend(&low_bound, 1, MPI_INT, 0, SLAVE_TO_MASTER_TAG, MPI_COMM_WORLD, &request);
  79. //send the upper bound next without blocking, to the master
  80. MPI_Isend(&upper_bound, 1, MPI_INT, 0, SLAVE_TO_MASTER_TAG + 1, MPI_COMM_WORLD, &request);
  81. //finally send the processed portion of data without blocking, to the master
  82. MPI_Isend(&mat_result[low_bound][0], (upper_bound - low_bound) * NUM_COLUMNS_B, MPI_DOUBLE, 0, SLAVE_TO_MASTER_TAG + 2, MPI_COMM_WORLD, &request);
  83. }
  84. /* master gathers processed work*/
  85. if (rank == 0) {
  86. for (i = 1; i < size; i++) {// untill all slaves have handed back the processed data
  87. //receive low bound from a slave
  88. MPI_Recv(&low_bound, 1, MPI_INT, i, SLAVE_TO_MASTER_TAG, MPI_COMM_WORLD, &status);
  89. //receive upper bound from a slave
  90. MPI_Recv(&upper_bound, 1, MPI_INT, i, SLAVE_TO_MASTER_TAG + 1, MPI_COMM_WORLD, &status);
  91. //receive processed data from a slave
  92. MPI_Recv(&mat_result[low_bound][0], (upper_bound - low_bound) * NUM_COLUMNS_B, MPI_DOUBLE, i, SLAVE_TO_MASTER_TAG + 2, MPI_COMM_WORLD, &status);
  93. }
  94. end_time = MPI_Wtime();
  95. printf("\nRunning Time = %f\n\n", end_time - start_time);
  96. printArray();
  97. }
  98. MPI_Finalize(); //finalize MPI operations
  99. return 0;
  100. }
  101. void makeAB()
  102. {
  103. for (i = 0; i < NUM_ROWS_A; i++) {
  104. for (j = 0; j < NUM_COLUMNS_A; j++) {
  105. mat_a[i][j] = i + j;
  106. }
  107. }
  108. for (i = 0; i < NUM_ROWS_B; i++) {
  109. for (j = 0; j < NUM_COLUMNS_B; j++) {
  110. mat_b[i][j] = i*j;
  111. }
  112. }
  113. }
  114. void printArray()
  115. {
  116. for (i = 0; i < NUM_ROWS_A; i++) {
  117. printf("\n");
  118. for (j = 0; j < NUM_COLUMNS_A; j++)
  119. printf("%8.2f ", mat_a[i][j]);
  120. }
  121. printf("\n\n\n");
  122. for (i = 0; i < NUM_ROWS_B; i++) {
  123. printf("\n");
  124. for (j = 0; j < NUM_COLUMNS_B; j++)
  125. printf("%8.2f ", mat_b[i][j]);
  126. }
  127. printf("\n\n\n");
  128. for (i = 0; i < NUM_ROWS_A; i++) {
  129. printf("\n");
  130. for (j = 0; j < NUM_COLUMNS_B; j++)
  131. printf("%8.2f ", mat_result[i][j]);
  132. }
  133. printf("\n\n");
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement