Advertisement
Guest User

Untitled

a guest
Feb 21st, 2020
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.84 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <mpi.h>
  6.  
  7. #define N 10
  8. #define eps 0.00001
  9.  
  10. //Count of rows to one process
  11. int get_rows_count_process(int curr_rank, int size){
  12. int general = N/size;
  13. int rest = N % size;
  14. return general + (curr_rank < rest ? 1 : 0);
  15. }
  16.  
  17. //Offset from the first element in matrix
  18. int get_offset(int curr_rank, int size){
  19. int res = 0;
  20. for(int i = 0; i < curr_rank; i++){
  21. res += get_rows_count_process(i, size);
  22. }
  23. return res;
  24. }
  25.  
  26. //Create matrix A
  27. double* create_matrix_A(int rank, int size){
  28. int row_cnt = get_rows_count_process(rank, size);
  29. double* part_process = (double*)calloc(row_cnt*N, sizeof(double));
  30. int offset = get_offset(rank, size);
  31. for(int i = 0; i < row_cnt; i++){
  32. for(int j = 0; j < N; j++){
  33. part_process[i*N + j] = (i == (j - offset))? 2 : 1;
  34. }
  35. }
  36. return part_process;
  37. }
  38.  
  39. //Create vector b
  40. double* create_vector_b(int rank, int size){
  41. double* vector = (double*)calloc(N, sizeof(double));
  42.  
  43. if(rank == 0){
  44. for(int i = 0; i < N; i++){
  45. vector[i] = N + 1;
  46. }
  47. for(int i = 1; i < size; i++){
  48. MPI_Send(vector, N, MPI_DOUBLE, i, 128, MPI_COMM_WORLD);
  49. }
  50. }else{
  51. MPI_Recv(vector, N, MPI_DOUBLE, 0, 128, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  52. }
  53. return vector;
  54. }
  55.  
  56.  
  57. //Multiple matrix by vector
  58. double* Matrix_by_vector(double *M, double *V, int rank, int size)
  59. {
  60. int row_count_proc = get_rows_count_process(rank, size);
  61. double *result = (double*)calloc(row_count_proc, sizeof(double));
  62. for(int i = 0; i < row_count_proc; i++){
  63. for(int j = 0; j < N; j++)
  64. {
  65. result[i] += M[N*i + j]*V[j];
  66. }
  67. }
  68. return result;
  69. }
  70.  
  71. //Array of beginigns of parts_processes
  72. int* get_begin_positions(int size){
  73. int* positions = (int*)calloc(size, sizeof(int));
  74. for(int i = 0; i < size; i++){
  75. positions[i] = get_offset(i, size);
  76. }
  77. return positions;
  78. }
  79.  
  80. //Array of sizes of blocks of matrix
  81. int* get_sizes(int size){
  82. int* sizes = (int*)calloc(size, sizeof(int));
  83. for(int i = 0; i < size; i++){
  84. sizes[i] = get_rows_count_process(i, size);
  85. }
  86. return sizes;
  87. }
  88.  
  89. double* differ_vectros(double* a, double* b, int rank, int size){
  90. double* res = (double*)calloc(N, sizeof(double));
  91. if(rank == 0){
  92. for(int i = 0; i < N; i++){
  93. res[i] = a[i] - b[i];
  94. }
  95. for(int i = 1; i < size; i++){
  96. MPI_Send(res, N, MPI_DOUBLE, i, 130, MPI_COMM_WORLD);
  97. }
  98. }else{
  99. MPI_Recv(res, N, MPI_DOUBLE, 0, 130, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  100. }
  101. return res;
  102. }
  103.  
  104. void print_matrix(double* matrix, int rank, int size){
  105. int part_size = get_rows_count_process(rank, size);
  106. for(int process = 0; process < size; process++){
  107. MPI_Barrier(MPI_COMM_WORLD);
  108. if(rank == process){
  109. for(int i = 0; i < part_size; i++){
  110. for(int j = 0; j < N; j++){
  111. printf("%0.0f", matrix[i*N + j]);
  112. }
  113. printf("\n");
  114. }
  115. }
  116. }
  117. }
  118.  
  119. double* Minimal_Nevazki(double *A, double *b, int rank, int size)
  120. {
  121. double* X = (double*)calloc(N, sizeof(double));
  122.  
  123. int* positions = get_begin_positions(size);
  124. int* part_sizes = get_sizes(size);
  125.  
  126. double crit_module;
  127. double chisl_Tau;
  128. double del_Tau;
  129.  
  130. while(1){
  131. double* AbX = Matrix_by_vector(A, X, rank, size);
  132. double* Ax = (double*)calloc(N, sizeof(double));
  133. MPI_Allgatherv(AbX, part_sizes[rank], MPI_DOUBLE, Ax, part_sizes, positions, MPI_DOUBLE, MPI_COMM_WORLD);
  134.  
  135. double* Y = differ_vectros(Ax, b, rank, size);
  136.  
  137. double* AbY = Matrix_by_vector(A, Y, rank, size);
  138. double* Ay = (double*)calloc(N, sizeof(double));
  139. MPI_Allgatherv(AbY, part_sizes[rank], MPI_DOUBLE, Ay, part_sizes, positions, MPI_DOUBLE, MPI_COMM_WORLD);
  140.  
  141. chisl_Tau = 0.0;
  142. del_Tau = 0.0;
  143.  
  144. if(rank == 0){
  145. for(int i = 0; i < N; i++){
  146. chisl_Tau += Ay[i]*Y[i];
  147. del_Tau += Ay[i]*Ay[i];
  148. }
  149.  
  150. for(int i = 1; i < size; i++){
  151. MPI_Send(&chisl_Tau, 1, MPI_DOUBLE, i, 123, MPI_COMM_WORLD);
  152. MPI_Send(&del_Tau, 1, MPI_DOUBLE, i, 123, MPI_COMM_WORLD);
  153. }
  154. }else{
  155. MPI_Recv(&chisl_Tau, 1, MPI_DOUBLE, 0, 123, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  156. MPI_Recv(&del_Tau, 1, MPI_DOUBLE, 0, 123, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  157. }
  158.  
  159. if(rank == 0){
  160. double crit_1 = 0.0;
  161. double crit_2 = 0.0;
  162.  
  163. for(int i = 0; i < N; i++){
  164. crit_1 += pow(Ax[i] - b[i], 2);
  165. crit_2 += pow(b[i], 2);
  166. }
  167. crit_1 = sqrt(crit_1);
  168. crit_2 = sqrt(crit_2);
  169. crit_module = crit_1/crit_2;
  170.  
  171. for(int i = 1; i < size; i++){
  172. MPI_Send(&crit_module, 1, MPI_DOUBLE, i, 125, MPI_COMM_WORLD);
  173. }
  174. }else{
  175. MPI_Recv(&crit_module, 1, MPI_DOUBLE, 0, 125, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  176. }
  177.  
  178. if(crit_module < eps){
  179. free(Y);
  180. free(AbY);
  181. free(Ay);
  182. free(AbX);
  183. free(Ax);
  184. break;
  185. }
  186.  
  187. chisl_Tau = chisl_Tau/del_Tau;
  188. for(int i = 0; i < N; i++){
  189. X[i] = X[i] - chisl_Tau*Y[i];
  190. }
  191. }
  192. return X;
  193. }
  194.  
  195. int main(int argc, char **argv) {
  196. int size, rank;
  197. MPI_Init(&argc, &argv);
  198. MPI_Comm_size(MPI_COMM_WORLD, &size);
  199. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  200.  
  201. double *A = create_matrix_A(rank, size);
  202. double *b = create_vector_b(rank, size);
  203. if(rank == 0)
  204. std::cout << "Curr epsilon:" << eps << std::endl;
  205.  
  206.  
  207. //print_matrix(A, rank, size);
  208. double start = MPI_Wtime();
  209. double *X = Minimal_Nevazki(A, b, rank, size);
  210. double end = MPI_Wtime();
  211.  
  212. /*if(rank == 0){
  213. for(int i = 0; i < N; i++)
  214. printf("X[%d]= %lf\n", i, X[i]);
  215. }*/
  216.  
  217. printf("Time taken: %lf sec.\n", end - start);
  218.  
  219. free(A);
  220. free(b);
  221. free(X);
  222.  
  223. MPI_Finalize();
  224. return 0;
  225. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement