如何使用 boost MPI 出现死锁情况(我使用 MPICH 编译器)?
How to have a deadlock scenario with boost MPI (I use MPICH compiler)?
我试图找出在什么情况下潜在阻塞的 boost mpi "send" 会实际阻塞并导致死锁。
#include <boost/mpi.hpp>
#include <iostream>
int main(int argc, char *argv[])
{
boost::mpi::environment env{argc, argv};
boost::mpi::communicator world;
if (world.rank() == 0)
{
char buffer[14];
const char *c = "Hello, world from 1!";
world.send(1, 1, c, 13);
std::cout << "1--11111\n";
world.send(1, 1, c, 13);
std::cout << "1--22222\n";
world.recv(1, 1, buffer, 13);
std::cout << "1--33333\n";
world.recv(1, 1, buffer, 13);
std::cout << "1--44444\n";
buffer[13] = '[=10=]';
std::cout << buffer << "11 \n";
}
else
{
char buffer[14];
const char *c = "Hello, world from 2!";
world.send(0, 1, c, 13);
std::cout << "2--11111\n";
world.send(0, 1, c, 13);
std::cout << "2--22222\n";
world.recv(0, 1, buffer, 13);
std::cout << "2--33333\n";
world.recv(0, 1, buffer, 13);
std::cout << "2--44444\n";
buffer[13] = '[=10=]';
std::cout << buffer << "22 \n";
}
}
但它运行得很好并且按照这个顺序:
2--11111
2--22222
1--11111
1--22222
1--33333
1--44444
Hello, world 11
2--33333
2--44444
Hello, world 22
如果有人能给我一个我实际上陷入僵局的场景,我将不胜感激。
潜在阻塞的 boost mpi 是如何工作的?
谢谢。
通常最简单的强制阻止行为的方法是使用更大的消息,导致切换到所谓的 'rendezvous' 协议,发件人将等待收件人 post 匹配在开始数据传输之前接收操作。
实施可能会也可能不会完成 MPI_Send
在发布接收之前。您的代码不是正确的 MPI 应用程序。在下雨的满月期间,在特定的网络上,它可能会因特定的消息大小而死锁。
实际上,它主要取决于消息大小,因为实现通常会将小消息发送到预分配的缓冲区。根据您的实施,可能会有调整参数。
MPI 描述了几种通信模式。默认是 blocking1 或 standard 模式,如上所述。 同步 发送 (MPI_Ssend
) 必须等待接收被发布。这将保证死锁。
A buffered 发送 (MPI_Bsend
) 必须完成,即使未发布接收也是如此。除了这些模式之外,还有 nonblocking 或 immediate 调用将始终在本地完成,但可能尚未复制数据。两者都将保证不会出现死锁。但是 boost.MPI.
只支持后者
1: blocking 在术语中仅表示调用阻塞,直到可以重新使用发送缓冲区。要么因为它被发送了,要么因为它被本地缓冲了。另请查看 the standard。
我试图找出在什么情况下潜在阻塞的 boost mpi "send" 会实际阻塞并导致死锁。
#include <boost/mpi.hpp>
#include <iostream>
int main(int argc, char *argv[])
{
boost::mpi::environment env{argc, argv};
boost::mpi::communicator world;
if (world.rank() == 0)
{
char buffer[14];
const char *c = "Hello, world from 1!";
world.send(1, 1, c, 13);
std::cout << "1--11111\n";
world.send(1, 1, c, 13);
std::cout << "1--22222\n";
world.recv(1, 1, buffer, 13);
std::cout << "1--33333\n";
world.recv(1, 1, buffer, 13);
std::cout << "1--44444\n";
buffer[13] = '[=10=]';
std::cout << buffer << "11 \n";
}
else
{
char buffer[14];
const char *c = "Hello, world from 2!";
world.send(0, 1, c, 13);
std::cout << "2--11111\n";
world.send(0, 1, c, 13);
std::cout << "2--22222\n";
world.recv(0, 1, buffer, 13);
std::cout << "2--33333\n";
world.recv(0, 1, buffer, 13);
std::cout << "2--44444\n";
buffer[13] = '[=10=]';
std::cout << buffer << "22 \n";
}
}
但它运行得很好并且按照这个顺序:
2--11111
2--22222
1--11111
1--22222
1--33333
1--44444
Hello, world 11
2--33333
2--44444
Hello, world 22
如果有人能给我一个我实际上陷入僵局的场景,我将不胜感激。 潜在阻塞的 boost mpi 是如何工作的?
谢谢。
通常最简单的强制阻止行为的方法是使用更大的消息,导致切换到所谓的 'rendezvous' 协议,发件人将等待收件人 post 匹配在开始数据传输之前接收操作。
实施可能会也可能不会完成 MPI_Send
在发布接收之前。您的代码不是正确的 MPI 应用程序。在下雨的满月期间,在特定的网络上,它可能会因特定的消息大小而死锁。
实际上,它主要取决于消息大小,因为实现通常会将小消息发送到预分配的缓冲区。根据您的实施,可能会有调整参数。
MPI 描述了几种通信模式。默认是 blocking1 或 standard 模式,如上所述。 同步 发送 (MPI_Ssend
) 必须等待接收被发布。这将保证死锁。
A buffered 发送 (MPI_Bsend
) 必须完成,即使未发布接收也是如此。除了这些模式之外,还有 nonblocking 或 immediate 调用将始终在本地完成,但可能尚未复制数据。两者都将保证不会出现死锁。但是 boost.MPI.
1: blocking 在术语中仅表示调用阻塞,直到可以重新使用发送缓冲区。要么因为它被发送了,要么因为它被本地缓冲了。另请查看 the standard。