Transferring Multiple Dynamic MPI Arrays

I am trying to use ISend()two arrays: arr1,arr2and an integer nwhose size is equal arr1,arr2. I realized from this post that sending a structure containing all three is not an option, as it nis known only at runtime. Obviously, I need to nbe the first, because otherwise the receiving process would not know how many elements to get. What is the most efficient way to achieve this without using blockcing Send()?

+1
source share
3 answers

Sending the size of the array is redundant (and inefficient) because MPI provides a way to search for incoming messages without receiving them, which provides enough information for the correct memory allocation. The study is performed with help MPI_PROBEthat is very similar to MPI_RECV, except that it does not accept buffer related arguments. The probe operation returns a state object that can then be queried for the number of elements of a given MPI data type that can be retrieved from the contents of the message using MPI_GET_COUNT, so explicitly sending the number of elements becomes unnecessary.

Here is a simple example with two ranks:

if (rank == 0)
{
    MPI_Request req;

    // Send a message to rank 1
    MPI_Isend(arr1, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &req);
    // Do not forget to complete the request!
    MPI_Wait(&req, MPI_STATUS_IGNORE);
}
else if (rank == 1)
{
    MPI_Status status;

    // Wait for a message from rank 0 with tag 0
    MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
    // Find out the number of elements in the message -> size goes to "n"
    MPI_Get_count(&status, MPI_DOUBLE, &n);
    // Allocate memory
    arr1 = malloc(n*sizeof(double));
    // Receive the message. ignore the status
    MPI_Recv(arr1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}

MPI_PROBE MPI_ANY_SOURCE MPI_ANY_TAG. , .

, , . , , . . .

+5

-, ( = n = ) arr1 arr2 0. i.e .

no. . .

0.

- i.e. arr1 arr2

arr1 arr2 , , = 0. , .

++, C . Send Isend.

    #include <mpi.h>
    #include <iostream>

    using namespace std;

    int main(int argc, char*argv[])
    {
        MPI::Init (argc, argv);

        int rank = MPI::COMM_WORLD.Get_rank();
        int no_of_processors = MPI::COMM_WORLD.Get_size();
        MPI::Status status;

        double *arr1;

        if (rank == 0)
        {
            //  Setting some Random n
            int n = 10;

            arr1 = new double[n];

            for(int i = 0; i < n; i++)
            {
                arr1[i] = i;
            }

            int part = n / no_of_processors;
            int offset = n % no_of_processors;

            //  cout << part << "\t" << offset << endl;

            for(int i = 1; i < no_of_processors; i++)
            {
                int start   = i*part;
                int end     = start + part - 1;

                if (i == (no_of_processors-1))
                {
                    end += offset;
                }

                //  cout << i << " Start: " << start << "  END: " << end;

                //  Element_Count
                int e_count = end - start + 1;

                //  cout << " e_count: " << e_count << endl;
                //  Sending
                MPI::COMM_WORLD.Send(
                                        &e_count,
                                        1,
                                        MPI::INT,
                                        i,
                                        0
                                    );

                //  Sending Arr1
                MPI::COMM_WORLD.Send(
                                        (arr1+start),
                                        e_count,
                                        MPI::DOUBLE,
                                        i,
                                        1
                                    );
            }
        }
        else
        {
            //  Element Count
            int e_count;

            //  Receiving elements count
            MPI::COMM_WORLD.Recv (   
                                    &e_count,
                                    1,
                                    MPI::INT,
                                    0,
                                    0,
                                    status
                                 );

            arr1 = new double [e_count];
            //  Receiving FIrst Array
            MPI::COMM_WORLD.Recv (
                                    arr1,
                                    e_count,
                                    MPI::DOUBLE,
                                    0,
                                    1,
                                    status
                                 );

            for(int i = 0; i < e_count; i++)
            {
                cout << arr1[i] << endl;
            }
        }

        //  if(rank == 0) 
        delete [] arr1;

        MPI::Finalize();

        return 0;
    }
0

@Histro , , , Irecv/Isend - , MPI lib. , /. 2 :

  • (, ) ( , 0 = ). ( ), . . , , ( ). , Isend Irecv, , recv. , B_cast MPI_Reduce.

  • Lazy Master , . , . - , , , , 18, , - . . , . . Isend/Irecv.

0

Source: https://habr.com/ru/post/1606144/


All Articles