Влияет ли вызов MPI-барьера на каждый поток в MPI-процессе?


Влияет ли вызов MPI_Barrier на каждый поток в MPI-процессе или только на сам поток это делает звонок? Для вашего сведения, мое приложение MPI будет работать с MPI_THREAD_MULTIPLE.

Спасибо.

1 2

1 ответ:

Способ думать об этом состоит в том, что MPI_Barrier (и другие коллективы) являются блокирующими вызовами функций, которые блокируют до тех пор, пока все процессы в коммуникаторе не завершат функцию. Это, я думаю, немного облегчает понимание того, что должно произойти; функциональные блоки, но другие потоки беспрепятственно продолжают свой путь.

Поэтому рассмотрим следующий фрагмент кода (общий флаг "сделано" сбрасывается для связи между потоками не так, как вы должны делать поток общение, поэтому, пожалуйста, не используйте это в качестве шаблона для чего-либо):

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

int main(int argc, char**argv) {
    int ierr, size, rank;
    int provided;
    volatile int done=0;
    MPI_Comm comm;

    ierr = MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
    if (provided == MPI_THREAD_SINGLE) {
        fprintf(stderr,"Could not initialize with thread support\n");
        MPI_Abort(MPI_COMM_WORLD,1);
    }

    comm = MPI_COMM_WORLD;
    ierr = MPI_Comm_size(comm, &size);
    ierr = MPI_Comm_rank(comm, &rank);

    if (rank == 1) sleep(10);

    #pragma omp parallel num_threads(2) default(none) shared(rank,comm,done)
    {
        #pragma omp single
        {
        /* spawn off one thread to do the barrier,... */
        #pragma omp task 
        {
            MPI_Barrier(comm);
            printf("%d -- thread done Barrier\n", rank);
            done = 1;
            #pragma omp flush
        }

        /* and another to do some printing while we're waiting */
        #pragma omp task
        {
            while(!done) {
                printf("%d -- thread waiting\n", rank);
                sleep(1);
            }
        }
        }
    }
    MPI_Finalize();

    return 0;
}
Ранг 1 спит в течение 10 минут, и все ранги начинают барьер в одном потоке. Если вы выполняете это с mpirun -np 2, вы ожидаете, что первый из потоков ранга 0s ударит по барьеру, а другой будет циклически печатать и ждать - и, конечно же, это то, что происходит:
$ mpirun -np 2 ./threadbarrier
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
0 -- thread waiting
1 -- thread waiting
0 -- thread done Barrier
1 -- thread done Barrier