You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.1 KiB

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include "Ttiming.h"
  5. #include <mpi.h>
  6. #include <stdio.h>
  7. using namespace std;
  8. void array_alloc(long **&arr, long arrsize)
  9. {
  10. try
  11. {
  12. arr = new long* [arrsize];
  13. arr[0] = new long [arrsize*arrsize];
  14. for(long i = 1; i < arrsize; ++i)
  15. arr[i] = arr[i-1] + arrsize;
  16. }
  17. catch (bad_alloc& ex)
  18. {
  19. cerr << "Could not allocate memory for array" << endl;
  20. exit(1);
  21. }
  22. }
  23. void vect_alloc(long *&arr, long arrsize)
  24. {
  25. try
  26. {
  27. arr = new long [arrsize];
  28. }
  29. catch (bad_alloc& ex)
  30. {
  31. cerr << "Could not allocate memory for vector" << endl;
  32. exit(1);
  33. }
  34. }
  35. void array_destroy(long **arr)
  36. {
  37. delete [] arr[0];
  38. delete [] arr;
  39. }
  40. int main(int argc, char *argv[])
  41. {
  42. long **A=NULL, **B=NULL, **C=NULL, *B_rot=NULL, *vect=NULL, *vect_c=NULL, *C_rot=NULL;
  43. long rozmiar=0, porcja_new=0;
  44. char *endptr;
  45. TTiming tt;
  46. long i;
  47. MPI::Status status;
  48. if (argc < 2)
  49. {
  50. cerr << "Usage: " << argv[0] << " <size>" << endl;
  51. exit(1);
  52. }
  53. rozmiar = strtol(argv[1], &endptr, 10);
  54. if (*endptr)
  55. {
  56. cerr << "Invalid array size format" << endl;
  57. exit(1);
  58. }
  59. if (rozmiar <= 0 || rozmiar > 2000)
  60. {
  61. cerr << "The number of matrix dimension must be in range [1,2000]" << endl;
  62. exit(1);
  63. }
  64. MPI::Init(argc, argv);
  65. int taskid = MPI::COMM_WORLD.Get_rank();
  66. int ntasks = MPI::COMM_WORLD.Get_size();
  67. //alokacja macierzy
  68. array_alloc(A, rozmiar);
  69. if (taskid == 0)
  70. {
  71. array_alloc(B, rozmiar);
  72. vect_alloc(B_rot, rozmiar*rozmiar);
  73. vect_alloc(C_rot, rozmiar*rozmiar);
  74. }
  75. // porcja - ile wektorów dostaje jeden proces do liczenia
  76. // jeżeli liczba procesów większa od wektorów - każdy proces dostaje po jednym, niektóre wcale
  77. long porcja = (rozmiar>=ntasks) ? (long)round(rozmiar*1.0/ntasks) : 1;
  78. porcja *= rozmiar; //porcję mnożymy przez ilość elementów w jednym wektorze
  79. porcja_new = porcja;
  80. array_alloc(C, rozmiar);
  81. vect_alloc(vect, porcja);
  82. vect_alloc(vect_c, porcja);
  83. if (taskid == 0)
  84. {
  85. // wypełnienie macierzy A liczbami "losowymi"
  86. for (long i=0; i<rozmiar; ++i)
  87. for (long j=0; j<rozmiar; ++j)
  88. A[i][j] = 3*i+j+1; //test
  89. //A[i][j] = (long)(sin(i) * i * j) % 10;
  90. // wypełnienie macierzy B liczbami "losowymi"
  91. for (long i=0; i<rozmiar; ++i)
  92. for (long j=0; j<rozmiar; ++j)
  93. B[i][j] = j; //test
  94. //B[i][j] = (long)(cos(j) *(i+j)) % 10;
  95. // dokonaj obracania macierzy
  96. for (long i=0; i<rozmiar; ++i)
  97. for (long j=0; j<rozmiar; ++j)
  98. B_rot[i*rozmiar+j] = B[j][i];
  99. }
  100. //wysyłanie macierzy A do wszystkich
  101. MPI::COMM_WORLD.Bcast(&A[0][0], rozmiar*rozmiar, MPI::LONG, 0);
  102. if (taskid == 0 && false)
  103. {
  104. cout << endl << "WEKTOR DANYCH: " << endl;
  105. for (i=0; i<rozmiar*rozmiar; ++i)
  106. cout << B_rot[i] << " ";
  107. cout << endl;
  108. }
  109. MPI::COMM_WORLD.Barrier();
  110. //dla wszystkich lub "rozmiar" procesów należy zadać porcję do obliczenia
  111. MPI::COMM_WORLD.Scatter(&B_rot[0], porcja, MPI::LONG, &vect[0], porcja, MPI::LONG,0);// (rozmiar>=ntasks) ? 0 : ntasks-rozmiar);
  112. //
  113. // część licząca ---------------------------------------------------------------------------------
  114. //
  115. MPI::COMM_WORLD.Barrier();
  116. if (taskid == 0)
  117. tt.Begin();
  118. if (taskid == ntasks -1) //przelicz porcję dla ostatniego procesu (w przypadku dzielenia z resztą)
  119. {
  120. porcja_new = (rozmiar - (porcja/rozmiar)*(ntasks-1))*rozmiar;
  121. // myk jest taki, że muszę podać jakąś niezerową porcję do gathera,
  122. // mimo, że proces nie ma żadnych (sensownych) danych do przetworzenia
  123. if (porcja_new > 0)
  124. porcja = porcja_new;
  125. }
  126. for (i=0; i<porcja_new; ++i)
  127. {
  128. vect_c[i] = 0;
  129. for (long k=0; k<rozmiar; ++k)
  130. {
  131. vect_c[i] += A[i%rozmiar][k]*vect[(i/rozmiar)*rozmiar+k];
  132. }
  133. }
  134. MPI::COMM_WORLD.Barrier();
  135. if (taskid == 0)
  136. {
  137. long elapsed = tt.End();
  138. cout << "Time: " << elapsed << " ms" << endl;
  139. }
  140. // zwróć wszystko do programu głównego
  141. MPI::COMM_WORLD.Gather(&vect_c[0], porcja, MPI::LONG, &C_rot[0], porcja, MPI::LONG, 0);
  142. if (taskid == 0 && false)
  143. {
  144. for (i=0; i<rozmiar*rozmiar; ++i)
  145. {
  146. cout << C_rot[i] << " ";
  147. }
  148. cout << endl;
  149. }
  150. /*
  151. array_destroy(A);
  152. array_destroy(B);
  153. array_destroy(C);
  154. */
  155. MPI::Finalize();
  156. exit(0);
  157. }