我想知道什么时候需要使用屏障?例如,在分散/聚集之前/之后我需要它吗?或者OMPI应该确保在分散/收集之前所有进程都已达到这一点?同样,在广播之后我可以期望所有进程都已收到消息吗?
答案 0 :(得分:25)
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仅在少数情况下有用。大多数情况下,您不关心您的进程是否同步。更好地阅读阻塞和非阻塞呼叫!
答案 1 :(得分:15)
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
。
答案 2 :(得分:1)
可能不经常使用MPI_Barrier(),但它很有用。 实际上,即使您使用同步通信,MPI_Send / Recv()也只能确保两个进程同步。 在我的项目中,我使用的是cuda + MPI项目,它是异步通信。 我发现在某些情况下如果我不使用MPI_Barrier()后跟Wait()函数,那么两个进程(gpu)想要同时向对方传输数据的情况很可能会发生,这可能很糟糕降低程序效率。 上面的错误让我很生气,带我几天才找到它。因此,在程序中使用MPI_Isend / Irecv时,可能会仔细考虑是否使用MPI_Barrier()。有时同步进程不仅是必要的,而且还必须,尤其是你的程序正在处理设备。