OpenMPI MPI_Barrier问题

hol*_*ola 7 c mpi openmpi

我使用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();
Run Code Online (Sandbox Code Playgroud)

对于mpirun -n 2 ./a.out

输出应为:P0 P1 ...

有时输出:P0 P0再次P1 P1

这是怎么回事?

Jen*_*edt 13

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

您可以尝试使用时间戳为输出添加前缀,并将所有这些保存到不同的文件中,每个MPI进程一个.

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

那么你的问题就会消失.

  • @suszterpatt:`MPI_Wtime()`通常不是全局/同步时钟!(只有在定义了'MPI_WTIME_IS_GLOBAL`并且为真时) (3认同)

Sha*_*hin 11

MPI_Barrier()没有错.

正如Jens所提到的,你没有看到预期输出的原因是因为stdout在每个进程上都被缓冲了.无法保证来自多个进程的打印将按顺序显示在调用进程中.(如果每个进程的stdout被转移到主进程实时打印,那将导致大量不必要的通信!)

如果你想说服自己屏障有效,你可以尝试写一个文件.将多个进程写入单个文件可能会导致额外的复杂化,因此您可以将每个proc写入一个文件,然后在屏障之后交换他们写入的文件.例如:

    Proc-0           Proc-1
      |                 |
 f0.write(..)     f1.write(...) 
      |                 |
      x  ~~ barrier ~~  x
      |                 |
 f1.write(..)     f0.write(...) 
      |                 |
     END               END
Run Code Online (Sandbox Code Playgroud)

示例实施:

#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;

}
Run Code Online (Sandbox Code Playgroud)

运行代码后,您应该得到以下结果:

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

[me@home]$ cat file_1.out
P1: before Barrier
P0: after Barrier
Run Code Online (Sandbox Code Playgroud)

对于所有文件,"后障碍"语句将始终显示在以后.


pow*_*rox 5

MPI 程序中不保证输出顺序。

这与 MPI_Barrier 完全无关。

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

如果您确实想要的话,实现此目的的最优雅的方法是让进程将其消息发送到一个等级,例如等级 0,并让等级 0 按照接收消息的顺序或按等级排序打印输出。

再次强调,不要花太多时间尝试对 MPI 程序的输出进行排序。不实用,用处不大。