Проблемы с OpenMPI MPI_Barrier - PullRequest
       31

Проблемы с OpenMPI MPI_Barrier

7 голосов
/ 03 марта 2011

У меня возникли некоторые проблемы с синхронизацией с использованием реализации MPMP_Barrier в OpenMPI:

int rank;
int nprocs;

int rc = MPI_Init(&argc, &argv);

if(rc != MPI_SUCCESS) {
    fprintf(stderr, "Unable to set up MPI");
    MPI_Abort(MPI_COMM_WORLD, rc);
}

MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);


printf("P%d\n", rank);
fflush(stdout);

MPI_Barrier(MPI_COMM_WORLD);

printf("P%d again\n", rank);

MPI_Finalize();

для mpirun -n 2 ./a.out

вывод должен быть: P0 P1 ...

вывод равен иногда : снова P0 P0, снова P1 P1

что происходит?

Ответы [ 3 ]

13 голосов
/ 03 марта 2011

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

Вы можете попытаться поставить перед выходными данными метку времени и сохранить все это в разных файлах, по одному на каждый процесс MPI.

Затем, чтобы проверить ваш журнал, вы можете объединить два файла и отсортировать их по временной метке.

Тогда ваша проблема должна исчезнуть.

11 голосов
/ 03 марта 2011

В MPI_Barrier () нет ничего плохого.

Поскольку Дженс упомянул , причина, по которой вы не видите ожидаемого результата, заключается в том, что stdout буферизуется в каждом процессе.Нет гарантии, что отпечатки из нескольких процессов будут отображаться в вызывающем процессе по порядку.(Если стандартный вывод из каждого процесса будет передан в основной процесс для печати в режиме реального времени, это приведет к большому количеству ненужного общения!)

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

    Proc-0           Proc-1
      |                 |
 f0.write(..)     f1.write(...) 
      |                 |
      x  ~~ barrier ~~  x
      |                 |
 f1.write(..)     f0.write(...) 
      |                 |
     END               END

Пример реализации:

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    char filename[20];
    int rank, size;
    FILE *fp;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (rank < 2) { /* proc 0 and 1 only */ 
        sprintf(filename, "file_%d.out", rank);
        fp = fopen(filename, "w");
        fprintf(fp, "P%d: before Barrier\n", rank);
        fclose(fp);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    if (rank < 2) { /* proc 0 and 1 only */ 
        sprintf(filename, "file_%d.out", (rank==0)?1:0 );
        fp = fopen(filename, "a");
        fprintf(fp, "P%d: after Barrier\n", rank);
        fclose(fp);
    }

    MPI_Finalize();
    return 0;

}

После выполнения кода вы должны получить следующие результаты:

[me@home]$ cat file_0.out
P0: before Barrier
P1: after Barrier

[me@home]$ cat file_1.out
P1: before Barrier
P0: after Barrier

Для всех файлов«после барьера» заявления всегда будут появляться позже.

3 голосов
/ 04 марта 2011

Порядок вывода не гарантируется в программах MPI.

Это никак не связано с MPI_Barrier.

Кроме того, я бы не стал тратить слишком много времени на беспокойство о порядке вывода с помощью программ MPI.

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

Опять же, не тратьте слишком много времени на попытки упорядочить вывод программ MPI. Это не практично и бесполезно.

...