Проблемы барьера 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-программ. Это непрактично и бесполезно.