MPI_Barrier似乎无法正常工作,重新排序printf(stdout)消息

时间:2017-03-12 02:38:30

标签: c mpi

以下是一个非常基本的MPI程序

#include <mpi.h>
#include <stdio.h>

int main(int argc, char * argv[]) {
    int rank;
    int size;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    MPI_Barrier(MPI_COMM_WORLD);
    printf("Hello from %d\n", rank);
    MPI_Barrier(MPI_COMM_WORLD);
    printf("Goodbye from %d\n", rank);
    MPI_Barrier(MPI_COMM_WORLD);
    printf("Hello 2 from %d\n", rank);
    MPI_Barrier(MPI_COMM_WORLD);
    printf("Goodbye 2 from %d\n", rank);
    MPI_Finalize();
    return 0;
}

您希望输出为(对于2个进程)

Hello from 0
Hello from 1
Goodbye from 1
Goodbye from 0
Hello 2 from 1
Hello 2 from 0
Goodbye 2 from 0
Goodbye 2 from 1

或者类似的东西(应该对hellos和goodbyes进行分组,但不保证流程顺序)。

这是我的实际输出:

Hello from 0
Goodbye from 0
Hello 2 from 0
Goodbye 2 from 0
Hello from 1
Goodbye from 1
Hello 2 from 1
Goodbye 2 from 1

我是否从根本上误解了MPI_Barrier应该做什么?从我所知,如果我只使用它一次,那么它给了我预期的结果,但不仅如此,它似乎绝对没有。

我之前已经发现许多类似的问题,但我所看到的问题中的问题误解了MPI_Barrier的功能。

1 个答案:

答案 0 :(得分:0)

  

应该将hellos和再见分组

他们不应该在printf函数内部有额外的(MPI异步)缓冲,而另一个缓冲是stdout从多个MPI进程收集到单个用户终端。

printf只打印到libc(glibc)的内存缓冲区,有时刷新到真实文件描述符(stdout;使用fflush刷新缓冲区);和fprintf(stderr,...)通常比stdout

的缓冲更少

远程任务由mpirun / mpiexec启动,通常使用ssh远程shell,执行stdout / stderr转发。 ssh(以及TCP也将)缓冲数据,当来自ssh的数据通过mpirun / mpiexec或其他实体(多个数据流被多路复用为一个)时,可以重新排序。

你得到的是从第一个进程中的4个字符串缓冲并在其出口处刷新(所有字符串都打印到stdout,通常具有几千字节的缓冲区);并且第二个进程中的另外4个字符串也被缓冲,直到退出。所有4个字符串都由ssh或其他启动方法发送到您的控制台,作为单个&#34;数据包&#34;并且你的控制台只显示两个包含4行的包,每个包含一些顺序,&#34; 4_lines_packet_from_id_0; 4_lines_packet_from_id_1;&#34;或作为&#34; 4_lines_packet_from_id_1; 4_lines_packet_from_id_0;&#34;。

  

MPI_Barrier应该做什么?

MPI_Barrier同步部分代码,但它不能在libc / glibc打印和文件I / O函数中禁用任何缓冲,也不能在ssh或其他远程shell中禁用。

如果所有进程都在具有同步系统时钟的计算机上运行(它们将在您拥有单个计算机时运行,并且它们应该在您的群集上有ntpd时),则可以为每个{{{}添加时间戳字段1}}检查真正的顺序是否尊重你的障碍(printf查找当前时间,并且没有额外的缓冲)。即使gettimeofdayprintf重新排序邮件,您也可以对带时间戳的输出进行排序。

ssh