Advertisement
Guest User

Untitled

a guest
Feb 19th, 2020
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.42 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <stdio.h>
  6. #include <mpi.h>
  7.  
  8. void Matrix_by_vector(int N, double *M, double *V, double *R)
  9. //N - размерность, M - матрица, V - вектор, R - реузультат
  10. {
  11. int rank, size;
  12. MPI_Status status;
  13. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  14. MPI_Comm_size(MPI_COMM_WORLD, &size);
  15.  
  16. int mod = N%size;
  17.  
  18. double *localresult = new double[N/size];
  19. double matrix[N][N];//local matirx
  20. MPI_Barrier(MPI_COMM_WORLD);//Пока все процессы не вызовут эту функцию, вызвавшие будут ждать
  21.  
  22. //Передача частей матрицы процессам(осуществляется 0-ым процессом)
  23. if(rank==0){
  24. for(int i = 0; i < N/size + ((0 < mod) ? (1) : (0)); i++)
  25. for(int j = 0; j < N/size; j++)
  26. matrix[i][j] = M[j + (N*i)];
  27. for(int i = 1; i < size; i++){
  28. MPI_Send(M+((N*N/size)*(i)), N*(N/size + ((i < mod) ? (1) : (0))), MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  29. }
  30. }
  31. else{
  32. MPI_Recv(matrix, N*(N/size + ((rank < mod) ? (1) : (0))), MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  33. }
  34.  
  35. //Передача 0-ым процессом вектора, на который умножается матрица
  36. if(rank == 0){
  37. for(int i = 0; i < size; i++){
  38. if(i != rank){
  39. MPI_Send(V, N, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
  40. }
  41. }
  42. } else{
  43. MPI_Recv(V, N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  44. }
  45.  
  46. //Выполнение умножения матрицы на вектор
  47. for(int i = 0; i < N/size + ((rank < mod) ? (1) : (0)); i++){
  48. localresult[i] = 0;
  49. for(int j = 0; j < N; j++)
  50. {
  51. localresult[i] += matrix[i][j]*V[j];
  52. }
  53. }
  54.  
  55. //Сбор результирующего вектора
  56. if(rank == 0){
  57. for(int i = 0; i < N/size; i++)
  58. R[i] = localresult[i];
  59. for(int i = 1; i < size; i++){
  60. MPI_Recv(R+((N/size)*(i)), (N)/size + ((i < mod)? 1 : 0), MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  61. }
  62. }
  63. else{
  64. MPI_Send(localresult, N/size + ((rank < mod)? 1 : 0), MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  65. }
  66. }
  67.  
  68. int Minimal_Nevazki(int N, double *A, const double *b, double *X, double eps)
  69. //N - размерность, A - матрица, b - вектор свободных членов, X - вектор результат, eps - точность
  70. {
  71. int count = 0;//Число итераций
  72. double *R = new double[N];
  73. double *Y = new double[N];
  74. double *Xn = new double[N];//приближение
  75.  
  76. double crit_module;
  77. double chisl_Tau;
  78. double del_Tau;
  79.  
  80. for(int i = 0; i < N; i++){
  81. Xn[i] = 0;//Начальное приближение делаем равным 0
  82. }
  83.  
  84. do{
  85. Matrix_by_vector(N, A, Xn, R);
  86. for(int i = 0; i < N; i++){
  87. Y[i] = R[i] - b[i];
  88. }
  89.  
  90. Matrix_by_vector(N, A, Y, R);
  91.  
  92. chisl_Tau = 0.0;
  93. del_Tau = 0.0;
  94. for(int i = 0; i < N; i++)
  95. {
  96. chisl_Tau += R[i]*Y[i];
  97. del_Tau += R[i]*R[i];
  98. }
  99. chisl_Tau = chisl_Tau/del_Tau;
  100. for(int i = 0; i < N; i++){
  101. X[i] = Xn[i] - chisl_Tau*Y[i];
  102. }
  103.  
  104.  
  105. Matrix_by_vector(N, A, X, R);
  106. double crit_1 = 0.0;
  107. double crit_2 = 0.0;
  108. for(int i = 0; i < N; i++){
  109. crit_1 += pow(R[i] - b[i], 2);
  110. crit_2 += pow(b[i], 2);
  111. }
  112. crit_1 = sqrt(crit_1);
  113. crit_2 = sqrt(crit_2);
  114. crit_module = crit_1/crit_2;
  115.  
  116. //Обновляем приближение
  117. for(int i = 0; i < N; i++){
  118. Xn[i] = X[i];
  119. }
  120.  
  121. count++;
  122. }
  123. while (crit_module >= eps);
  124.  
  125. delete[](R);
  126. delete[](Y);
  127. delete[](Xn);
  128. return count;
  129. }
  130.  
  131. int main(int argc, char **argv) {
  132.  
  133. int rank, size;
  134.  
  135. MPI_Init(&argc, &argv);
  136. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  137. MPI_Comm_size(MPI_COMM_WORLD, &size);
  138.  
  139. int N = atoi(argv[1]);
  140. double A[N][N];
  141. double u[N];
  142.  
  143. //Нулевой процесс заполняет матрицу A и начальный вектор u
  144. if(rank == 0)
  145. {
  146. //Заполнение матрицы А
  147. for(int i = 0; i < N; i++){
  148. for(int j = 0; j < N; j++){
  149. if(i == j){
  150. A[i][j] = 2.0;
  151. } else{
  152. A[i][j] = 1.0;
  153. }
  154. }
  155. }
  156.  
  157. for(int i = 0; i < N; i++){
  158. u[i] = sin((2*M_1_PI*i)/N);
  159. }
  160. }
  161.  
  162. double b[N];
  163. Matrix_by_vector(N, (double *)A, u, b);
  164.  
  165. double X[N];//Вектор решений
  166. double epsilon = pow(10, -5);//Точность
  167.  
  168. //std::cout << "Curr epsilon:" << epsilon << std::endl;
  169.  
  170. double timer = MPI_Wtime();
  171. int count_steps = Minimal_Nevazki(N,(double *)A, b, X, epsilon);
  172. timer = MPI_Wtime() - timer;
  173.  
  174. if(rank == 0){
  175. std::cout << "Count steps:" << count_steps << std::endl;
  176. std::cout << "Time:" << timer << std::endl;
  177. for(int i = 0; i < N; i++){
  178. std::cout << "X[" << i << "]:" << X[i] << " U[" << i << "]:" << u[i] << std::endl;
  179. }
  180. }
  181.  
  182. MPI_Finalize();
  183. return 0;
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement