Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Создать матрицы А,B размерности n n в корневом процессе с
- //номером q. Получить матрицу С = А 2 – В 2 .
- #include <iostream>
- #include <stdio.h>
- #include <math.h>
- #include <mpi.h>
- using namespace std;
- void f2(double* A, int N)
- {
- for(int i = 0; i < N ; i++)
- {
- for(int j = 0; j < N ; j++)
- {
- cout << A[i*N + j];
- }
- cout << endl;
- }
- cout << endl;
- }
- void f1(double* A, int N, int k)
- {
- for(int i = 0; i < N ; i++)
- {
- for(int j = 0; j < N ; j++)
- {
- A[i*N + j] = k;
- }
- }
- f2(A,N);
- }
- void f(double* a, double* A_B_N, double* K, int m, int N) //Произведение матриц
- {
- for(int i = 0 ; i < m ; i++)
- {
- for(int j = 0 ; j < N ; j++)
- {
- K[i * N + j] = 0;
- for(int k = 0 ; k < N ; k++)
- {
- K[i * N + j] += a[i * N + k] * A_B_N[k * N + j];
- }
- }
- }
- // cout << endl << "----------------------" << endl;
- // for(int i = 0 ; i < m ; i++)
- // {
- // for(int j = 0 ; j < N ; j++)
- // {
- // cout << K[i * N + j];
- // }
- // }
- // cout << endl;
- }
- int main(int argc, char** argv)
- {
- int myrank, size, i, N;
- double *A = 0, *B = 0, *C = 0, *K1 = 0, *K2 = 0; // A и В это входные матрицы С результат К1 и К2 промежуточные матрицы для параллельных вычислений
- double *a = 0, *b = 0; // a и b часть матриц А и В соответсвенно а А2 и В2 полные копии матриц А и В нужные для получения строк в промежуточных матрицах К1 и К2
- int *sendcounts = 0, //массив количества элементов в процессе
- *displs = 0; // массив смещений
- double t1, t2;
- MPI_Init( &argc, &argv );
- MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
- MPI_Comm_size( MPI_COMM_WORLD, &size );
- if (myrank == 0)
- {
- cout << "Vvedite N";
- cin >> N;
- t1 = MPI_Wtime();
- }
- MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
- if (myrank == 0) // выделение памяди для входных матриц и выходного
- {
- C = new double[N * N];
- }
- int m = N/size + (N%(size)>(myrank)?1:0); // определения количества ЭЛЕМЕНТОВ(т.е. кол-во элементов массива, а не кол-во строк этого массива) в каждом процессе
- int g = m * N;
- sendcounts = new int[size]; // заполнение массива sendcounts
- MPI_Gather(&g,1,MPI_INT,sendcounts,1,MPI_INT,0,MPI_COMM_WORLD);// Здесь заполняеться в корневом процессе массив sendcounts
- displs = new int[size]; // заполнение массива displs(смещений)
- displs[0] = 0;
- for (i = 1;i < size ; ++i){
- displs[i] = displs[i-1] + sendcounts[i-1]; // Возможно не верно вычисляет смещения
- }
- 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 копии матриц А и В
- double *C1 = new double[N * N];
- if (myrank == 0)
- {
- f1(A,N,2); // заполнение исходной матрицы А
- f1(B,N,1); // заполнение исходной матрицы B
- }
- MPI_Bcast(A, N*N, MPI_DOUBLE, 0, MPI_COMM_WORLD);
- MPI_Bcast(B, N*N, MPI_DOUBLE, 0, MPI_COMM_WORLD);
- MPI_Scatterv(A, sendcounts, displs, MPI_DOUBLE, a, m * N, MPI_DOUBLE, 0, MPI_COMM_WORLD ); // рассылка частей матрицы A по процессам т.е. в каждый(возможно и в нулевой) процесс присылается своя часть А и присваевается а
- MPI_Scatterv(B, sendcounts, displs, MPI_DOUBLE, b, m * N, MPI_DOUBLE, 0, MPI_COMM_WORLD );
- f(a, A, K1, m, N);
- f(b, B, K2, m, N);
- MPI_Gatherv(K1, m * N, MPI_DOUBLE, A, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD ); // посылка результата в корневой процесс матрица А
- MPI_Gatherv(K2, m * N, MPI_DOUBLE, B, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD ); // посылка результата в корневой процесс матрица В
- for(int i = 0 ; i < m ; i++)
- {
- for(int j = 0 ; j < N ; j++)
- {
- C1[i * N + j] = K1[i * N + j] - K2[i * N + j]; // Мы не теряем ускарение т.к. это происходит в каждом потоке
- }
- }
- MPI_Gatherv(C1, m * N, MPI_DOUBLE, C, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD ); // посылка результата в корневой процесс матрица С
- // if(myrank == 0)
- // {
- // for(int i = 0 ; i < N ; i++)
- // {
- // for(int j = 0 ; j < N ; j++)
- // {
- // C[i * N + j] = A[i * N + j] - B[i * N + j]; // Из-за этого цикла мы теряем ускарение(параллельное вычисление) (например N = 1000 то итераций будет 1000000 в одном потоке а это очень много по сравнению с другими и как следствие параллельности не будет имеется ввиду ускарение слабое будет и возможно по скорости программа будет уступать однопоточной программе)
- // }
- // }
- // }
- if (myrank == 0)
- {
- cout << endl << "----------" << endl;
- f2(A,N); // вывод результата
- f2(B,N); // вывод результата
- f2(C,N);
- t2 = MPI_Wtime();
- cout << endl << "time "<< t2-t1<<endl;
- }
- MPI_Finalize();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement