Advertisement
Guest User

Untitled

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