[Из песочницы] Бесполезный отложенный неблокирующий обмен сообщениями в MPI: лайт-аналитика и туториал для тех, кто немножечко «в теме»

v0ik2-rxhe1gexlrsumqpwhslbu.jpeg
#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