30

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

4

3 回答 3

29

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 仅在少数情况下有用。大多数时候,您并不关心您的进程是否同步。更好地阅读阻塞和非阻塞调用!

于 2012-11-09T10:25:11.250 回答
20

例如,一种用途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.

于 2012-11-09T13:13:27.890 回答
0

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

于 2015-09-29T11:17:21.787 回答