Проблемы OpenMPI MPI_Barrier

У меня возникли некоторые проблемы с синхронизацией с использованием реализации 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%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 снова

в чем дело?


person hola    schedule 03.03.2011    source источник


Ответы (4)


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

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

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

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

person Jens Gustedt    schedule 03.03.2011
comment
Использование временных меток может быть не идеальным, если процессы MPI выполняются на разных узлах, если только вы не можете гарантировать синхронизацию часов. - person Shawn Chin; 03.03.2011
comment
@Shawn: для этого есть MPI_Wtime(). - person suszterpatt; 03.03.2011
comment
@suszterpatt: MPI_Wtime() обычно НЕ являются глобальными/синхронизированными часами! (Это только в том случае, если MPI_WTIME_IS_GLOBAL определено и верно) - person Zulan; 03.03.2011
comment
Насколько я знаю, MPI_Wtime в OpenMPI не синхронизируется. - person Shawn Chin; 04.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

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

person Shawn Chin    schedule 03.03.2011

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

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

Кроме того, я бы не тратил слишком много времени на заботу о порядке вывода в программах MPI.

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

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

person powerrox    schedule 03.03.2011

Добавляя к предыдущим ответам здесь, ваш MPI_BARRIER работает нормально.

Однако, если вы просто хотите увидеть, как он работает, вы можете принудительно приостановить выполнение (SLEEP(1)) на мгновение, чтобы позволить выводу наверстать упущенное.

person Shobhan Roy    schedule 29.07.2020