2

我正在尝试使用 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 收到了消息(“1 到达屏障”)。

0 是第一轮的获胜者

0 收到:1 到达巴里

0 是第 2 轮的获胜者

1是第一轮的失败者

1 发送到达消息

2是第一轮的获胜者

2 收到:3 到达巴里

2是第2轮的失败者

2 发送到达消息

3是第一轮的失败者

3 发送到达信息

0 收到:2 到达巴里

0 发送唤醒信息

0 发送唤醒信息

1 收到:从 0 唤醒消息,第 1 轮有标签

2 收到:从 0 唤醒消息,在第 2 轮带有标签

2 发送唤醒消息

3 收到:从 2 唤醒消息,在第 1 轮带有标签

4

3 回答 3

2

根据我的经验,你很可能有观察问题,而不是你的底层算法。通常printf这种设置中的 s 只是乱序到达。你必须

  • 在输出中添加时间戳
  • 写入不同的文件,每个 MPI 进程一个
  • 通过根据您的时间戳排序将它们重新合并在一起
于 2011-10-21T06:50:57.217 回答
1

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

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

于 2011-10-22T00:21:12.087 回答
0

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

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

于 2011-10-21T06:15:03.387 回答