【问题标题】:OpenMPI MPI_Barrier problemsOpenMPI MPI_Barrier 问题
【发布时间】:2011-07-08 02:40:37
【问题描述】:

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

发生了什么事?

【问题讨论】:

    标签: c mpi openmpi


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 如果 MPI 进程在不同的节点上运行,则依赖时间戳可能并不理想,除非您可以保证时钟是同步的。
    • @Shawn:有 MPI_Wtime() 。
    • @suszterpatt: MPI_Wtime() 通常不是全局/同步时钟! (仅当 MPI_WTIME_IS_GLOBAL 已定义且为 true 时)
    • AFAIK,OpenMPI 中的 MPI_Wtime 未同步。
    【解决方案2】:

    MPI_Barrier() 没有任何问题。

    作为Jens mentioned,您看不到预期输出的原因是因为每个进程都缓冲了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”语句总是会在后面出现。

    【讨论】:

      【解决方案3】:

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

      这根本与 MPI_Barrier 无关。

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

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-21
          • 2015-04-25
          • 2013-03-12
          • 1970-01-01
          • 2021-11-08
          • 2020-09-16
          • 2011-10-04
          • 2021-04-03
          相关资源
          最近更新 更多