我正在尝试使用MPI实现锦标赛障碍。这是我写的代码。我只写了到达阶段和唤醒阶段
//Arrival phase
while(1)
{
if((!strcmp(round[my_id][round_num].role,"winner"))||(!strcmp(round[my_id][round_num].role,"champion")))
{
printf("%d is the winner of round %d\n",my_id,round_num);
MPI_Recv(&reach_msg, sizeof(reach_msg), MPI_BYTE, round[my_id][round_num].opponent, tag, MPI_COMM_WORLD, &status);
printf("%d received: %s\n",my_id,reach_msg);
}
else if(!strcmp(round[my_id][round_num].role,"loser"))
{
printf("%d is the loser of round %d\n",my_id,round_num);
sprintf(reach_msg,"%d arrived at the barrier",my_id);
MPI_Send(reach_msg,strlen(reach_msg+1),MPI_BYTE,round[my_id][round_num].opponent,tag,MPI_COMM_WORLD);
MPI_Recv(wakeup_msg,sizeof(wakeup_msg),MPI_BYTE,round[my_id][round_num].opponent,tag,MPI_COMM_WORLD,&status);
printf("%d received: %s\n",my_id,wakeup_msg);
}
if(round_num==num_rounds)
break;
else
round_num++;
}
printf("%d is out of arrival tree\n",my_id);
//wakeup tree
while(1)
{
printf("%d prints: round num is: %d\n",my_id,round_num);
if(round_num==0)
break;
sprintf(wakeup_msg,"wakeup msg from %d of %d",my_id,P);
if((!strcmp(round[my_id][round_num].role,"winner"))||(!strcmp(round[my_id][round_num].role,"champion")))
MPI_Send(wakeup_msg,strlen(wakeup_msg+1),MPI_BYTE,round[my_id][round_num].opponent,tag,MPI_COMM_WORLD);
round_num--;
}
MPI_Finalize();
return 0;
}
我不明白为什么会出现种族情况。我相信MPI_Send和MPI_Recv是阻塞函数。但是,有时它的行为并不那样
编辑:以下是竞争条件发生的示例输出。正如你所看到的,即使在1发送消息之前,0收到的消息(“1到达屏障”)也是如此。
0是第1轮的赢家
0收到:1到达了barrie
0是第2轮的胜利者
1是第1轮的输家
1发送到达消息msg
2是第1轮的获胜者
2收到:3到达了barrie
2是第2轮的输家
2发送到达消息msg
3是第1轮的输家
3发送到达消息msg
0收到:2到达了barrie
0发送唤醒消息
0发送唤醒消息
1收到:从0开始唤醒消息,第1轮有标签
2收到:从0开始唤醒消息,第2轮有标签
2发送唤醒消息
3收到:从第2轮带标签的2唤醒消息
答案 0 :(得分:2)
根据我的经验,您很可能有观察问题,而不是您的基础算法问题。通常,此类设置中的printf
只是无序到达。你必须
答案 1 :(得分:1)
对于调试mpi程序,print语句通常不是一个很好的解决方案。由于打印状态需要通过网络从不同节点发送到控制台,并且之前已缓存。
要调试它,您应该让每个处理器写入自己的输出文件。或者只让一个处理器打印语句,通过使用std :: cerr禁用缓存或以某种方式禁用printf的缓存。
答案 2 :(得分:0)
我不确定我是否完全理解您的问题...在您的问题中添加代码输出可能有所帮助。
我可以肯定地说,MPI_Send和MPI_Recv肯定是阻塞函数。您是否尝试使用非阻塞功能(即MPI_Isend和MPI_Irecv)?如果是的话,它能解决你的问题吗?