一个看似愚蠢的问题,但我似乎无法以某种方式找到明确的答案。
基本问题是我需要为MPI :: Isend提供相应的MPI :: Irecv吗?
即使消息发送是非阻塞的,只要我在重新使用发送缓冲区之前等待发送完成,我是否需要使用非阻塞接收&等待接收发送的缓冲区?
我的观点是,我希望在发送消息时使用非阻塞发送“执行其他操作”,但接收方进程将立即使用缓冲区,因此我希望它们阻塞直到真正接收到缓冲区。
似乎我应该能够接收到MPI :: Recv的消息,即使它们是用MPI :: Isend发送的,但我想知道我是否遗漏了什么?
一些简单的伪代码
if( rank == 0 ){
int r;
for ( int i = 0; i < n; i++ ){
// DO SOME STUFF HERE...
request.Wait(status);
request2.Wait(status);
request3.Wait(status);
r = i;
memcpy( key, fromKey(i), ...);
memcpy( trace, fromTrace(i), ...);
request = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag );
request2 = MPI::COMM_WORLD.Isend( key, 10, MPI::INT, node, tag );
request3 = MPI::COMM_WORLD.Isend( trace, nBytesTotal, MPI::BYTE, node, tag );
// DO SOME MORE STUFF HERE.
}
r = -1;
request = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag );
// Carry on ...
} else {
int r = -1;
MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status );
while( r >= 0 ){
MPI::COMM_WORLD.Recv( &key, 10, MPI::INT, 0, tag, status );
memcpy( saveKey, key, ...);
MPI::COMM_WORLD.Recv( &trace, nBytesTotal, MPI::BYTE, 0, tag, status );
memcpy( saveTrace, trace, ...);
MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status );
}
答案 0 :(得分:16)
不,您可以在通信的两端自由混合阻塞和非阻塞MPI操作。阻止与MPI调用何时将控制权返回给您的代码而不是与正在传输的消息的内容有关。
每条MPI消息都带有一个“信封”,其中包含其来源,目的地,标签和通信器。要成功接收消息,您的接收操作应仅匹配其信封。信封绝不指定消息的确切发送方式 - 是通过阻塞,是通过非阻塞操作,是同步发送(MPI_Ssend
)还是缓冲(MPI_Bsend
)。唯一的例外是所谓的“就绪模式”发送,它使用MPI_Rsend()
或MPI_Irsend()
启动,这要求匹配的接收操作已经发布或消息不会被传递。
这就是为什么在整个MPI标准中使用术语“匹配接收操作”而不是“相应的接收功能”。
答案 1 :(得分:0)
是的,这很好。不要求send / recv“种类”(或任何你想要称之为的种类)匹配。
答案 2 :(得分:0)
这不管你使用什么发送/接收;但实施很重要。您必须知道代码中的阻塞点。例如,在使用阻止通信时,您必须关注发送和接收呼叫 看看这段代码
if(rank==0)
{
MPI_Send(x to process 1)
MPI_Recv(y from process 1)
}
if(rank==1)
{
MPI_Send(y to process 0);
MPI_Recv(x from process 0);
}
在这种情况下会发生什么? 进程0将x发送到进程1并阻塞,直到进程1接收到x,进程0将y发送到进程0并阻塞,直到进程0收到y,但进程0被阻塞,因此进程1阻塞无穷大,直到你终止2个进程