Advertisement
alexdmin

lab3

Oct 20th, 2022
941
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.40 KB | None | 0 0
  1. //Создать матрицы А,B размерности n  n в корневом процессе с
  2. //номером q. Получить матрицу С = А 2 – В 2 .
  3.  
  4. #include <iostream>
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include <mpi.h>
  8.  
  9. using namespace std;
  10.  
  11. void f2(double* A, int N)
  12. {
  13.     for(int i = 0; i < N ; i++)
  14.     {
  15.         for(int j = 0; j < N ; j++)
  16.         {
  17.             cout << A[i*N + j];
  18.         }
  19.         cout << endl;
  20.     }
  21.     cout << endl;
  22. }
  23.  
  24. void f1(double* A, int N, int k)
  25. {
  26.     for(int i = 0; i < N ; i++)
  27.     {
  28.         for(int j = 0; j < N ; j++)
  29.         {
  30.             A[i*N + j] = k;
  31.         }
  32.     }
  33.  
  34.     f2(A,N);
  35. }
  36.  
  37. void f(double* a, double* A_B_N, double* K, int m, int N)     //Произведение матриц
  38. {
  39.     for(int i = 0 ; i < m ; i++)
  40.     {
  41.         for(int j = 0 ; j < N ; j++)
  42.         {
  43.             K[i * N + j] = 0;
  44.             for(int k = 0 ; k < N ; k++)
  45.             {
  46.                 K[i * N + j] += a[i * N + k] * A_B_N[k * N + j];
  47.             }
  48.         }
  49.     }
  50.     // cout << endl << "----------------------" << endl;
  51.     // for(int i = 0 ; i < m ; i++)
  52.     // {
  53.     //     for(int j = 0 ; j < N ; j++)
  54.     //     {
  55.     //         cout << K[i * N + j];                    
  56.     //     }
  57.     // }  
  58.     // cout << endl;  
  59. }
  60.  
  61. int main(int argc, char** argv)
  62. {
  63.     int myrank, size, i, N;
  64.     double *A = 0, *B = 0, *C = 0, *K1 = 0, *K2 = 0;    // A и В это входные матрицы  С результат К1 и К2 промежуточные матрицы для параллельных вычислений
  65.    
  66.     double *a = 0, *b = 0;    // a и b часть матриц А и В соответсвенно а А2 и В2 полные копии матриц А и В нужные для получения строк в промежуточных матрицах К1 и К2
  67.    
  68.     int *sendcounts = 0,    //массив количества элементов в процессе
  69.    
  70.     *displs = 0;  // массив смещений
  71.     double t1, t2;
  72.  
  73.     MPI_Init( &argc, &argv );
  74.     MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
  75.     MPI_Comm_size( MPI_COMM_WORLD, &size );
  76.  
  77.     if (myrank == 0)
  78.     {
  79.         cout << "Vvedite N";
  80.         cin >> N;
  81.         t1 = MPI_Wtime();
  82.     }
  83.        
  84.     MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
  85.    
  86.     if (myrank == 0)        // выделение памяди для входных матриц и выходного
  87.     {
  88.         C = new double[N * N];
  89.     }
  90.    
  91.     int m = N/size + (N%(size)>(myrank)?1:0);        // определения количества ЭЛЕМЕНТОВ(т.е. кол-во элементов массива, а не кол-во строк этого массива) в каждом процессе
  92.     int g = m * N;
  93.     sendcounts = new int[size];      // заполнение массива sendcounts
  94.    
  95.     MPI_Gather(&g,1,MPI_INT,sendcounts,1,MPI_INT,0,MPI_COMM_WORLD);// Здесь заполняеться в корневом процессе массив sendcounts
  96.    
  97.     displs = new int[size]; // заполнение массива displs(смещений)
  98.     displs[0] = 0;
  99.     for (i = 1;i < size ; ++i){
  100.         displs[i] = displs[i-1] + sendcounts[i-1];        // Возможно не верно вычисляет смещения
  101.     }
  102.  
  103.     A = new double[N * N];  B = new double[N * N];  a = new double[m * N]; b = new double[m * N];   K1 = new double[m * N];  K2 = new double[m * N]; //A2 = new double[N* N]; B2 = new double[N * N]; // A2 и B2 копии матриц А и В
  104.     double *C1 = new double[N * N];
  105.     if (myrank == 0)
  106.     {
  107.         f1(A,N,2);         // заполнение исходной матрицы А
  108.         f1(B,N,1);         // заполнение исходной матрицы B
  109.     }
  110.  
  111.     MPI_Bcast(A, N*N, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  112.     MPI_Bcast(B, N*N, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  113.    
  114.     MPI_Scatterv(A, sendcounts, displs, MPI_DOUBLE, a, m * N, MPI_DOUBLE, 0, MPI_COMM_WORLD );     // рассылка частей матрицы A по процессам      т.е. в каждый(возможно и в нулевой) процесс присылается своя часть А и присваевается а
  115.     MPI_Scatterv(B, sendcounts, displs, MPI_DOUBLE, b, m * N, MPI_DOUBLE, 0, MPI_COMM_WORLD );
  116.    
  117.     f(a, A, K1, m, N);
  118.     f(b, B, K2, m, N);
  119.    
  120.     MPI_Gatherv(K1, m * N, MPI_DOUBLE, A, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD );      // посылка результата в корневой процесс матрица А
  121.     MPI_Gatherv(K2, m * N, MPI_DOUBLE, B, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD );      // посылка результата в корневой процесс матрица В
  122.  
  123.     for(int i = 0 ; i < m ; i++)
  124.     {
  125.         for(int j = 0 ; j < N ; j++)
  126.         {
  127.             C1[i * N + j] = K1[i * N + j] - K2[i * N + j];         // Мы не теряем ускарение т.к. это происходит в каждом потоке
  128.         }
  129.     }
  130.  
  131.     MPI_Gatherv(C1, m * N, MPI_DOUBLE, C, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD );      // посылка результата в корневой процесс матрица С
  132.  
  133.  
  134.     // if(myrank == 0)
  135.     // {
  136.     //     for(int i = 0 ; i < N ; i++)
  137.     //     {
  138.     //         for(int j = 0 ; j < N ; j++)
  139.     //         {
  140.     //             C[i * N + j] = A[i * N + j] - B[i * N + j];         // Из-за этого цикла мы теряем ускарение(параллельное вычисление) (например N = 1000 то итераций будет 1000000 в одном потоке а это очень много по сравнению с другими и как следствие параллельности не будет имеется ввиду ускарение слабое будет и возможно по скорости программа будет уступать однопоточной программе)
  141.     //         }
  142.     //     }
  143.     // }
  144.  
  145.     if (myrank == 0)
  146.     {
  147.         cout << endl << "----------" << endl;
  148.         f2(A,N);   // вывод результата
  149.         f2(B,N);   // вывод результата
  150.         f2(C,N);
  151.         t2 = MPI_Wtime();
  152.         cout << endl << "time "<< t2-t1<<endl;
  153.     }
  154.  
  155.     MPI_Finalize();
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement