Проблемы барьера OpenMPI MPI

У меня есть некоторые проблемы с синхронизацией, используя реализацию OpenMPI MPI_Barrier:

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%dn", rank);
fflush(stdout);

MPI_Barrier(MPI_COMM_WORLD);

printf("P%d againn", rank);

MPI_Finalize();

для mpirun-n 2 ./а.из

выход должен быть: Р0 П1 ...

выход иногда: Р0 P0 снова П1 Р1 снова

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

3 ответов


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

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

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

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


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

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

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

    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

для всех файлов, заявления "после барьера" всегда появится позже.


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

Это вообще не связано с MPI_Barrier.

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

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

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