【发布时间】:2020-08-30 05:48:05
【问题描述】:
我正在我的程序中实现 MPI 非阻塞通信。我在 MPI_Isend man_page 上看到,它说:
非阻塞发送调用表明系统可能开始从发送缓冲区复制数据。在调用非阻塞发送操作后,发送方不应修改发送缓冲区的任何部分,直到发送完成。
我的代码是这样工作的:
// send messages
if(s > 0){
MPI_Requests s_requests[s];
MPI_Status s_status[s];
for(int i = 0; i < s; ++i){
// some code to form the message to send
std::vector<doubel> send_info;
// non-blocking send
MPI_Isend(&send_info[0], ..., s_requests[i]);
}
MPI_Waitall(s, s_requests, s_status);
}
// recv info
if(n > 0){ // s and n will match
for(int i = 0; i < n; ++i){
MPI_Status status;
// allocate the space to recv info
std::vector<double> recv_info;
MPI_Recv(&recv_info[0], ..., status)
}
}
我的问题是:我是否修改了发送缓冲区,因为它们位于内部大括号中(send_info 向量在循环结束后被杀死)?因此,这不是一种安全的通信方式吗?虽然我的程序现在运行良好,但我仍然被怀疑。感谢你的回复。
【问题讨论】:
-
这意味着当你在
send方法中时不要从另一个线程修改它。你没有这样做。 -
您的缓冲区是/可能在堆栈上分配,因此可以在发送之前被覆盖。在我看来,
MPI_Isend()的用法是错误的。 -
是的。我使用
std::vector,所以它是在堆栈上分配的。那么正确的做法是将MPI_Wait()和MPI_Isend()放在同一个循环中? -
是的,这是一种选择,但可能相当于阻止
MPI_Send()。其他选项包括在for循环之前分配一个巨大的缓冲区,并在之后分配一个MPI_Waitall()。另一种常见的技术是使用 2 个缓冲区:isend(buffer0);isend(buffer1);wait(req0);isend(buffer(0);wait(req1); ...,因此在保持内存使用合理的同时,计算和通信之间仍有一些重叠空间。 -
请注意,您不太可能在短消息中看到任何错误(以 Eager 模式发送),但更有可能在大消息中发送不正确的数据。
标签: c++ mpi nonblocking