9

我在使用 MPI_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

这是怎么回事?

4

4 回答 4

15

您的打印行在终端上出现的顺序不一定是打印的顺序。为此,您正在使用共享资源 ( stdout),因此必须始终存在排序问题。(并且fflush在这里没有帮助,stdout无论如何都是行缓冲的。)

您可以尝试在输出前加上时间戳,并将所有这些保存到不同的文件中,每个 MPI 进程一个。

然后要检查您的日志,您可以将两个文件合并在一起并根据时间戳进行排序。

那么你的问题应该消失了。

于 2011-03-03T16:33:33.387 回答
12

MPI_Barrier() 没有任何问题。

正如Jens 所提到的,您看不到预期输出的原因是因为 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

对于所有文件,“after Barrier”语句总是会在后面出现。

于 2011-03-03T17:38:34.517 回答
3

MPI 程序不保证输出顺序。

这根本与 MPI_Barrier 无关。

此外,我不会花太多时间担心 MPI 程序的输出排序。

实现这一点的最优雅的方法,如果你真的想的话,是让进程将它们的消息发送到一个等级,比如等级 0,然后让等级 0 按照它收到它们的顺序或按等级排序的顺序打印输出。

同样,不要花太多时间尝试从 MPI 程序中订购输出。它不实用,用处不大。

于 2011-03-03T22:42:20.153 回答
0

在此处添加先前的答案,您的 MPI_BARRIER 工作正常。

但是,如果您只是想看到它工作,您可以强制暂停执行 ( SLEEP(1)) 片刻以让输出赶上。

于 2020-07-29T20:27:14.083 回答