Advertisement
Guest User

Untitled

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