[Из песочницы] Бесполезный отложенный неблокирующий обмен сообщениями в MPI: лайт-аналитика и туториал для тех, кто немножечко «в теме»21.10.2018 22:48
#include "pch.h"
#include
#include
#include
#include
using namespace std;
void add(double *A, double *B, double *C, int n);
void sub(double *A, double *B, double *C, int n);
void mul(double *A, double *B, double *C, int n);
void div(double *A, double *B, double *C, int n);
int main(int argc, char **argv)
{
if (argc < 2)
{
return 1;
}
int n = atoi(argv[1]);
int rank;
double start_time, end_time;
MPI_Request request[7];
MPI_Status statuses[4];
double *A = new double[n];
double *B = new double[n];
double *C = new double[n];
double *D = new double[n];
double *E = new double[n];
double *G = new double[n];
double *T0 = new double[n];
double *T1 = new double[n];
double *T2 = new double[n];
for (int i = 0; i < n; i++)
{
A[i] = double(2 * i + 1);
B[i] = double(2 * i);
C[i] = double(0.003 * (i + 1));
D[i] = A[i] * 0.001;
E[i] = B[i];
G[i] = C[i];
}
cout.setf(ios::fixed);
cout << fixed << setprecision(9);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
{
start_time = MPI_Wtime();
MPI_Send_init(T0, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[0]);//
MPI_Send_init(T0, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[1]);//
MPI_Recv_init(T2, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[2]);//
MPI_Recv_init(T0, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[3]);//
MPI_Send_init(T2, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[4]);//
MPI_Recv_init(T0, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[5]);//
MPI_Recv_init(T2, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[6]);//
MPI_Start(&request[2]);
sub(A, B, T0, n);
MPI_Startall(2, &request[0]);
div(T0, G, T1, n);
MPI_Waitall(3, &request[0], statuses);
add(T1, T2, T0, n);
mul(T0, T1, T2, n);
MPI_Startall(2, &request[3]);
MPI_Wait(&request[3], &statuses[0]);
add(T0, T2, T1, n);
MPI_Startall(2, &request[5]);
MPI_Wait(&request[4], &statuses[0]);
MPI_Waitall(2, &request[5], statuses);
end_time = MPI_Wtime();
cout << "Clock resolution: " << MPI_Wtick() << " secs" << endl;
cout << "Thread " << rank << " execution time: " << end_time - start_time << endl;
}
if (rank == 1)
{
MPI_Recv_init(T1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[0]);//
MPI_Send_init(T0, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[1]);//
MPI_Recv_init(T1, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[2]);//
MPI_Send_init(T0, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[3]);//
MPI_Recv_init(T0, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[4]);//
MPI_Send_init(T1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[5]);//
MPI_Start(&request[0]);
add(C, C, T0, n);
MPI_Start(&request[1]);
MPI_Wait(&request[0], &statuses[0]);
mul(T1, G, T2, n);
MPI_Start(&request[2]);
MPI_Wait(&request[1], &statuses[0]);
add(T2, C, T0, n);
MPI_Start(&request[3]);
MPI_Wait(&request[2], &statuses[0]);
sub(T1, T0, T2, n);
MPI_Wait(&request[3], &statuses[0]);
MPI_Start(&request[4]);
MPI_Wait(&request[4], &statuses[0]);
add(T0, T2, T1, n);
MPI_Start(&request[5]);
MPI_Wait(&request[5], &statuses[0]);
}
if (rank == 2)
{
MPI_Recv_init(T1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[0]);//
MPI_Recv_init(T2, n, MPI_DOUBLE, 3, 0, MPI_COMM_WORLD, &request[1]);//
MPI_Send_init(T0, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[2]);//
MPI_Send_init(T0, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[3]);//
MPI_Recv_init(T2, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &request[4]);//
MPI_Recv_init(T1, n, MPI_DOUBLE, 3, 0, MPI_COMM_WORLD, &request[5]);//
MPI_Send_init(T2, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &request[6]);//
MPI_Startall(2, &request[0]);
mul(C, C, T0, n);
MPI_Startall(2, &request[2]);
MPI_Waitall(4, &request[0], statuses);
add(T1, T2, T0, n);
MPI_Start(&request[4]);
mul(T0, G, T1, n);
MPI_Wait(&request[4], &statuses[0]);
mul(T1, T2, T0, n);
MPI_Start(&request[5]);
MPI_Wait(&request[5], &statuses[0]);
mul(T0, T1, T2, n);
MPI_Start(&request[6]);
MPI_Wait(&request[6], &statuses[0]);
}
if (rank == 3)
{
MPI_Send_init(T0, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[0]);
MPI_Send_init(T1, n, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &request[1]);
mul(E, D, T0, n);
MPI_Start(&request[0]);
sub(T0, B, T1, n);
mul(T1, T1, T2, n);
MPI_Wait(&request[0], &statuses[0]);
sub(T1, G, T0, n);
mul(T0, T2, T1, n);
MPI_Start(&request[1]);
MPI_Wait(&request[1], &statuses[0]);
}
MPI_Finalize();
delete[] A, B, C, D, E, G, T0, T1, T2;
return 0;
}
void add(double *A, double *B, double *C, int n)
{
for (size_t i = 0; i < n; i++)
{
C[i] = A[i] + B[i];
}
}
void sub(double *A, double *B, double *C, int n)
{
for (size_t i = 0; i < n; i++)
{
C[i] = A[i] - B[i];
}
}
void mul(double *A, double *B, double *C, int n)
{
for (size_t i = 0; i < n; i++)
{
C[i] = A[i] * B[i];
}
}
void div(double *A, double *B, double *C, int n)
{
for (size_t i = 0; i < n; i++)
{
C[i] = A[i] / B[i];
}
}
© Habrahabr.ru