【问题标题】:When do I need to use MPI_Barrier()?什么时候需要使用 MPI_Barrier()?
【发布时间】:2012-10-29 15:20:59
【问题描述】:

我想知道什么时候需要使用屏障?例如,在分散/聚集之前/之后我是否需要它?或者 OMPI 是否应该在分散/聚集之前确保所有流程都已达到该点?同样,在广播之后,我可以期望所有进程都已经收到消息吗?

【问题讨论】:

    标签: synchronization mpi openmpi


    【解决方案1】:

    MPI-3.0 之前 MPI 中的所有集合操作都是阻塞的,这意味着在它们返回后使用传递给它们的所有缓冲区是安全的。特别是,这意味着当这些函数之一返回时,所有数据都已收到。 (但是,这并不意味着所有数据都已发送!) 因此,如果所有缓冲区都已经有效,则 MPI_Barrier 在集体操作之前/之后没有必要(或非常有用)。

    还请注意,MPI_Barrier 不会神奇地等待非阻塞调用。如果您使用非阻塞发送/接收,并且两个进程在发送/接收对之后在 MPI_Barrier 处等待,则不能保证进程在 MPI_Barrier 之后发送/接收所有数据。请改用 MPI_Wait(和朋友)。所以下面这段代码包含错误:

    /* ERRORNOUS CODE */
    
    Code for Process 0:
    Process 0 sends something using MPI_Isend
    MPI_Barrier(MPI_COMM_WORLD);
    Process 0 uses buffer passed to MPI_Isend // (!)
    
    Code for Process 1:
    Process 1 recvs something using MPI_Irecv
    MPI_Barrier(MPI_COMM_WORLD);
    Process 1 uses buffer passed to MPI_Irecv // (!)
    

    标有(!) 的两行都是不安全的!

    MPI_Barrier 仅在少数情况下有用。大多数时候,您并不关心您的进程是否同步。更好地了解阻塞和非阻塞调用!

    【讨论】:

    • 为什么第一个(!) 是错误的?进程 0 还会有自己的缓冲区吗?另外既然是发送,接收方不会改变它吧?
    • @JiewMeng MPI 不能在您调用 MPI_Isend 后立即从缓冲区中读取。如果您在(!) 更改它,您可能会发送一些不同的东西。我不太确定,但我认为在这种情况下行为是未定义的。
    • 由于 MPI-3.0 引入了非阻塞集合,我稍微更新了您的答案。
    • “特别是,这意味着当这些函数之一返回时,所有数据都已收到。(但是,这并不意味着所有数据都已发送!)” - 不是不一致吗?如何在不发送的情况下接收所有数据?也许你的意思是因为所有的集体操作都是阻塞的,所以在send 调用之后重用缓冲区和要发送的数据是安全的(因为这就是“阻塞”的含义),因为它是由 MPI“复制”的(不一定与缓冲发送MPI_Bsend 的方式相同)?当然,在阻塞发送返回时我们不能确定数据是否被接收是正确的。
    • @falconepl 你说得对,这就是我要说的。在我看来,措辞并没有矛盾,但我希望你的 cmets 能让那些和你有同样感受的人更清楚。谢谢!再次重复一遍:阻塞发送并不意味着消息已发送和接收,只是您可以重用缓冲区。阻塞接收调用意味着所有数据都已接收。
    【解决方案2】:

    MPI_Barrier 的一个用途是例如控制对外部资源(例如文件系统)的访问,而使用 MPI 无法访问该资源。例如,如果您希望每个进程按顺序将内容写入文件,您可以这样做:

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    for ( int ii = 0; ii < size; ++ii ) {
        if ( rank == ii ) {
            // my turn to write to the file
            writeStuffToTheFile();
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }
    

    这样,您可以确定没有两个进程同时调用writeStuffToTheFile

    【讨论】:

      【解决方案3】:

      可能 MPI_Barrier() 不经常使用,但它很有用。 事实上,即使您使用同步通信,MPI_Send/Recv() 也只能确保两个进程同步。 在我的项目中,一个 cuda+MPI 项目,我使用的只是异步通信。 我发现在某些情况下,如果我不使用 MPI_Barrier() 后跟 Wait() 函数,很可能会出现两个进程 (gpu) 想要同时相互传输数据的情况,这可能会很糟糕降低程序效率。 上面的虫子让我发疯,我花了几天时间才找到它。因此,当您在程序中使用 MPI_Isend/Irecv 时,您可能会仔细考虑是否使用 MPI_Barrier()。有时同步进程不仅是必要的,也是必须的,尤其是你的程序正在处理设备。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 2017-06-17
        • 2015-12-02
        • 2013-03-17
        • 2012-08-03
        • 1970-01-01
        相关资源
        最近更新 更多