Пытаюсь разобраться в некотором неблокирующем поведении mpi

#c #mpi #openmpi

#c #mpi #openmpi

Вопрос:

Итак, я попробовал некоторые вещи в MPI, чтобы получить представление об этом, и я получил некоторые результаты, которые я не могу объяснить, просматривая документацию. Я использую открытый mpi.

 #include <mpi.h>
#include <stdio.h>
#include <unistd.h>

#define PROBLEMSIZE 41 
int main(int argc, char** argv) {
    // Initialize the MPI environment
    MPI_Init(amp;argc, amp;argv);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, amp;world_size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, amp;world_rank);

    double send[PROBLEMSIZE];
    MPI_Request request[PROBLEMSIZE];
    int flag;
    int array_of_indices[PROBLEMSIZE];
    MPI_Status status[PROBLEMSIZE];

    if(world_rank == 0)
    {
        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            request[i] = MPI_REQUEST_NULL;
            send[i] = i;
        }

        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            MPI_Isend(amp;send[i],1,MPI_DOUBLE,1,i,MPI_COMM_WORLD,amp;request[i]);
        }
        MPI_Waitall(PROBLEMSIZE,request,status);
        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            //printf("%i count %i", i, status[i].count);
            //printf("%i cancel %i", i, status[i].cancel);
            printf("%i MPI_SOURCE %in", i, status[i].MPI_SOURCE);
            printf("%i MPI_TAG %in", i, status[i].MPI_TAG);
            printf("%i MPI_ERROR %in n", i, status[i].MPI_ERROR);
        }
        printf("thread 0 done");
    }

    if (world_rank == 1)
    {  
        sleep(10);
        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            MPI_Irecv(amp;send[i],1,MPI_DOUBLE,0,i,MPI_COMM_WORLD, amp;request[i]);
        }
        int outcount;
        
 
        do {
            MPI_Testsome(PROBLEMSIZE,request, amp;outcount, array_of_indices, MPI_STATUSES_IGNORE);
            printf("did some waiting, outcount is %in",outcount);
        } while (outcount != 0);



        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            printf("%f n",send[i]);
        }
        
        /*
        sleep(20);

        MPI_Testall(PROBLEMSIZE,request,MPI_STATUSES_IGNORE);

        for (int i = 0; i < PROBLEMSIZE; i  )
        {
            printf("%f n",send[i]);
        }
        */
    }



    MPI_Finalize();
    return 0;
}
 

/Редактировать

Чего я пытаюсь добиться, так это возможности отправлять произвольное количество данных с разными тегами из одного процесса в другой, где отправитель может блокировать и ждать, пока оно не будет получено, но получатель не должен блокировать, когда нечего получать.

Редактировать/

Итак, вот что сбивает меня с толку:

  1. MPI_Waitall в строке 36, похоже, на самом деле не блокируется, пока не произойдет обмен данными. Следовательно, последующая печать статуса приводит к полной подделке. (Источник = -2, Тег = -1, Ошибка = 0). Однако следующая строка printf("thread 0 done"); , похоже, ждет, пока программа не будет завершена, что более чем немного сбивает меня с толку.
  2. При попытке получить числа в строке 59, кажется, что только первые 16 совершают поездку, я попытался использовать MPI_Testall, MPI_Testsome и MPI_Waitsome для этого с тем же результатом. Я предположил, что это произошло из-за того, что буфер достиг какого-то предела, и попытался зациклить его несколько раз, пока он получал данные. Согласно документации outcount , должно содержаться количество полученных объектов, но всегда равно 0 при попытке сделать это с помощью MPI_Testsome и -32766 при попытке сделать это с помощью MPI_Waitsome. Оба эти явно подозрительные числа, но я не уверен, как и почему им удалось бы переполниться до -32766.
  3. Использование MPI_Waitall для получения данных в потоке 1 дает желаемое поведение, ставя под сомнение мое подозрение, что это проблема с буфером. Однако эта реализация — это не то, что я ищу, так как я хотел бы, чтобы поток 1 мог что-то делать и периодически проверять поступление новых данных.

Ответ №1:

  1. Я не уверен MPI_TAG MPI_SOURCE , что поля и релевантны, когда MPI_Status они связаны с запросом на отправку
  2. MPI_Test() а друзья — это неблокирующие подпрограммы, которые возвращаются немедленно. Я не уверен, чего вы здесь добиваетесь, но, возможно, вы захотите использовать MPI_Waitsome() вместо этого.

Комментарии:

1. 1. Это справедливо, хотя и не объясняет, почему MPI_Waitall right before, похоже, не блокируется до тех пор, пока принимающий поток не проверит. Насколько я понимаю, это должно быть ожидаемое поведение, нет? 2. Это имеет смысл, почему MPI_Test тогда записал бы 0 в outcount, поскольку это, вероятно, не было сделано к моменту проверки? Как я уже упоминал в посте, хотя Waitsome записывает -32766 в outcount, что я вообще не могу объяснить. Я отредактировал исходное сообщение, добавив немного о том, чего я хочу достичь, поскольку я достиг предела символов комментария.

2. Это ожидание возвращается, когда буфер отправки может быть использован повторно, это может произойти даже до отправки сообщения. -32766 очень вероятно MPI_UNDEFINED , см. Справочные страницы, чтобы узнать, как это интерпретировать.

3. Спасибо, что проясняет большинство моих недоразумений.