C++ MPI_Irecv未接收所有发送?
在这段简化的代码中,我试图实现的是:C++ MPI_Irecv未接收所有发送?,c++,openmpi,C++,Openmpi,在这段简化的代码中,我试图实现的是: 2种类型的进程(根进程和子进程,分别为id/rank=10和0-9) 初始化: root将侦听子级“已完成” 所有操作完成后,子级将侦听根通知 虽然没有赢家(尚未全部完成): 孩子们有20%的机会完成(并通知root他们完成) root将检查所有操作是否完成 如果全部完成:向“获胜者”的子女发送通知 我有如下代码: int numprocs, id, arr[10], winner = -1; bool stop = false; MPI_R
- 2种类型的进程(根进程和子进程,分别为id/rank=10和0-9)
- 初始化:
- root将侦听子级“已完成”
- 所有操作完成后,子级将侦听根通知
- 虽然没有赢家(尚未全部完成):
- 孩子们有20%的机会完成(并通知root他们完成)
- root将检查所有操作是否完成
- 如果全部完成:向“获胜者”的子女发送通知
int numprocs, id, arr[10], winner = -1;
bool stop = false;
MPI_Request reqs[10], winnerNotification;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
for (int half = 0; half < 1; half++) {
for (int round = 0; round < 1; round++) {
if (id == 10) { // root
// keeps track of who has "completed"
fill_n(arr, 10, -1);
for (int i = 0; i < 10; i++) {
MPI_Irecv(&arr[i], 1, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]);
}
} else if (id < 10) { // children
// listen to root of winner notification/indication to stop
MPI_Irecv(&winner, 1, MPI_INT, 10, 1, MPI_COMM_WORLD, &winnerNotification);
}
while (winner == -1) {
//cout << id << " is in loop" << endl;
if (id < 10 && !stop && ((rand() % 10) + 1) < 3) {
// children has 20% chance to stop (finish work)
MPI_Send(&id, 1, MPI_INT, 10, 0, MPI_COMM_WORLD);
cout << id << " sending to root" << endl;
stop = true;
} else if (id == 10) {
// root checks number of children completed
int numDone = 0;
for (int i = 0; i < 10; i++) {
if (arr[i] >= 0) {
//cout << "root knows that " << i << " has completed" << endl;
numDone++;
}
}
cout << "numDone = " << numDone << endl;
// if all done, send notification to players to stop
if (numDone == 10) {
winner = 1;
for (int i = 0; i < 10; i++) {
MPI_Send(&winner, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
}
cout << "root sent notification of winner" << endl;
}
}
}
}
}
MPI_Finalize();
我想也许我无法接收到一个数组,但我尝试了
if (id == 1) {
int x = 60;
MPI_Send(&x, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
} else if (id == 0) {
MPI_Recv(&arr[1], 1, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
cout << id << " recieved " << arr[1] << endl;
}
输出如下所示:
# 1 run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
9 b4 MPI_Finalize. winner is 2
0 b4 MPI_Finalize. winner is 2
# another run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
8 b4 MPI_Finalize. winner is 2
请注意,有些进程似乎没有收到来自父进程的通知?为什么,MPI_Wait
子进程只会挂起它们?那么我该如何解决这个问题呢
也
在您的情况下,MPI\U屏障的所有功能都会执行—它等待子级响应完成。请检查我的答案,寻找更好的解决方案
如果我不这样做,我想每个孩子的回答只需要几毫秒?因此,即使我不等待/设置障碍,我也希望在发送后不久仍能收到?除非进程最终占用资源,而其他进程不运行 请尝试此代码块(为了简单起见,省略了错误检查):
。。。
//根目录检查已完成的子目录数
int numDone=0;
MPI_状态[10];
MPI_Waitall(10,需求,状态);
对于(int i=0;i<10;i++){
...
编辑更好的解决方案:每个子级启动根赢家通知接收,并将其通知发送给根。
Root向阵列发送赢家通知接收,并进入等待接收所有通知的状态,然后将赢家的id发送给子级。 在(int round=0;round<1;round++)的
后面插入以下代码
if(id==10)
{//根
//跟踪谁已“完成”
memset(arr,-1,sizeof(arr));
对于(int i=0;i<10;i++)
{
MPI_Irecv(&arr[i],1,MPI_INT,i,0,MPI_COMM_WORLD,&reqs[i]);
}
}
否则,如果(id<10)
{//儿童
//聆听赢家通知/指示停止的根目录
MPI_Irecv(冠军、1名、MPI_INT、10名、1名、MPI_COMM_WORLD和winnerNotification);
}
如果(id<10)
{
而(((rand()%10)+1)<3);
//儿童有20%的机会停止(完成工作)
MPI_发送(&id,1,MPI_INT,10,0,MPI_COMM_WORLD);
std::你能追踪一下调用了多少次MPI_-Irecv(&arr[i],…)
吗?@MichaelSh,根据代码,应该是10次(每个孩子一次),对于每一轮?我在irecv之后添加了一个cout,没错,它被称为10次。关于MPI\u Wait
,在访问arr
之前你不需要调用它吗?在你的例子中,你使用阻塞发送/接收,但在你的应用中你使用异步接收…嗯…我想问题是我真的不想“等待”,如果有不完整的进程,我需要循环继续(如果我等待,循环将不会继续?).我的印象是,根检查每个循环上的arr应该可以工作?这意味着在某个时间点,arr应该填充来自已完成的Irecv
?所有MPI_屏障在您的情况下都可以-它会等待子响应完成。请检查我的答案,以获得更好的解决方案。嗯,有意义,有点。。。可能有点混乱,…但现在孩子们似乎没有收到赢家的“通知”,因此继续处于无限循环中,如果我尝试等待,循环将根本不会继续(如预期的那样)…我们是否应该在聊天中继续讨论??(为了简单起见,省略了错误检查)。实际上,检查简单MPI程序中的错误是毫无意义的,因为MPI标准要求默认错误处理程序中止程序执行。因此,MPI调用returnMPI\u SUCCESS
或干脆不返回(当程序终止时)。必须将每个通信器的错误处理程序显式更改为MPI\u ERRORS\u RETURN
,以便从失败的调用中接收MPI状态代码。
int numprocs, id, arr[10], winner = -1;
bool stop = false;
MPI_Request reqs[10], winnerNotification;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
srand(time(NULL) + id);
if (id < 10) {
MPI_Irecv(&winner, 1, MPI_INT, 10, 0, MPI_COMM_WORLD, &winnerNotification);
}
MPI_Barrier(MPI_COMM_WORLD);
while (winner == -1) {
cout << id << " is in loop ..." << endl;
if (id == 10) {
if (((rand() % 10) + 1) < 2) {
winner = 2;
for (int i = 0; i < 10; i++) {
MPI_Send(&winner, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
}
cout << "winner notifications sent" << endl;
}
}
}
cout << id << " b4 MPI_Finalize. winner is " << winner << endl;
MPI_Finalize();
# 1 run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
9 b4 MPI_Finalize. winner is 2
0 b4 MPI_Finalize. winner is 2
# another run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
8 b4 MPI_Finalize. winner is 2
...
// root checks number of children completed
int numDone = 0;
MPI_Status statuses[10];
MPI_Waitall(10, reqs, statuses);
for (int i = 0; i < 10; i++) {
...
if (id == 10)
{ // root
// keeps track of who has "completed"
memset(arr, -1, sizeof(arr));
for (int i = 0; i < 10; i++)
{
MPI_Irecv(&arr[i], 1, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]);
}
}
else if (id < 10)
{ // children
// listen to root of winner notification/indication to stop
MPI_Irecv(&winner, 1, MPI_INT, 10, 1, MPI_COMM_WORLD, &winnerNotification);
}
if (id < 10)
{
while(((rand() % 10) + 1) < 3) ;
// children has 20% chance to stop (finish work)
MPI_Send(&id, 1, MPI_INT, 10, 0, MPI_COMM_WORLD);
std::cout << id << " sending to root" << std::endl;
// receive winner notification
MPI_Status status;
MPI_Wait(&winnerNotification, &status);
// Process winner notification
}
else if (id == 10)
{
MPI_Status statuses[10];
MPI_Waitall(10, reqs, statuses);
// if all done, send notification to players to stop
{
winner = 1;
for (int i = 0; i < 10; i++)
{
MPI_Send(&winner, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
}
std::cout << "root sent notification of winner" << std::endl;
}
}