与MPI的竞争条件

时间:2011-10-21 05:55:08

标签: c mpi barrier

我正在尝试使用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唤醒消息

3 个答案:

答案 0 :(得分:2)

根据我的经验,您很可能有观察问题,而不是您的基础算法问题。通常,此类设置中的printf只是无序到达。你必须

  • 在输出中加上时间戳
  • 写入不同的文件,每个MPI流程一个
  • 根据您的时间戳排序将它们合并回来

答案 1 :(得分:1)

对于调试mpi程序,print语句通常不是一个很好的解决方案。由于打印状态需要通过网络从不同节点发送到控制台,并且之前已缓存。

要调试它,您应该让每个处理器写入自己的输出文件。或者只让一个处理器打印语句,通过使用std :: cerr禁用缓存或以某种方式禁用printf的缓存。

答案 2 :(得分:0)

我不确定我是否完全理解您的问题...在您的问题中添加代码输出可能有所帮助。

我可以肯定地说,MPI_Send和MPI_Recv肯定是阻塞函数。您是否尝试使用非阻塞功能(即MPI_Isend和MPI_Irecv)?如果是的话,它能解决你的问题吗?