Влияет ли вызов MPI_Barrier на каждый поток в процессе MPI? - PullRequest
2 голосов
/ 29 марта 2011

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

Спасибо.

1 Ответ

4 голосов
/ 29 марта 2011

Способ думать об этом состоит в том, что 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
...