Состояние гонки с MPI

Я пытаюсь реализовать турнирный барьер, используя 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 являются блокирующими функциями. Но иногда он так себя не ведет

EDIT: вот пример вывода, в котором возникает состояние гонки. Как видите, 0 получил сообщение («1 прибыл к барьеру») от 1 еще до того, как 1 отправил сообщение.

0 - победитель раунда 1

0 получено: 1 прибыл на барьер

0 - победитель 2 раунда

1 проигравший в 1 раунде

1 отправка сообщения

2 - победитель 1 раунда

2 получено: 3 прибыло на барьер

2 - проигравший во 2 раунде

2 отправка досягаемости msg

3 - проигравший раунд 1

3 отправка сообщения

0 получено: 2 прибыло на барьер

0 отправка пробуждающего сообщения

0 отправка пробуждающего сообщения

1 получено: сообщение о пробуждении от 0 с тегом в раунде 1

2 получено: сообщение о пробуждении от 0 с тегом в раунде 2

2 отправка сообщения пробуждения

3 получено: сообщение о пробуждении от 2 с тегом в раунде 1


person CuriousCoder    schedule 21.10.2011    source источник
comment
Под состоянием гонки я подразумеваю, что процесс-получатель получает сообщение еще до того, как процесс-отправитель отправит его!   -  person CuriousCoder    schedule 21.10.2011
comment
Маловероятно, что ваша программа нарушает причинно-следственную связь. Вы просто видите, что это напечатано таким образом. IIRC MPI (хотя это, вероятно, зависит от реализации) выполняет всю печать в процессе 0, что означает, что printf в процессе 1 фактически отправляет данные для печати процессом 0.   -  person user786653    schedule 21.10.2011
comment
@ user786653: Я запускаю этот код на той же машине. Мне выделен кластер машин. Что, если я раздам ​​код на разные машины кластера и запущу программу? будут ли операторы printf по-прежнему отправляться процессу 0 для печати?   -  person CuriousCoder    schedule 21.10.2011


Ответы (3)


Для отладки программ mpi операторы печати, как правило, не очень хорошее решение. Поскольку отчеты о печати необходимо отправлять на консоль с разных узлов по сети, они предварительно кэшируются.

Для отладки вы должны позволить каждому процессору писать в собственный выходной файл. Или позвольте только одному процессору печатать операторы, где вы отключите кэширование либо с помощью std::cerr, либо каким-то образом отключите кэширование printf.

person tune2fs    schedule 22.10.2011

По моему опыту, у вас, скорее всего, есть проблема с наблюдением, а не с вашим основным алгоритмом. Обычно printf в такой обстановке просто приходят не по порядку. Вы должны были бы

  • поместите метки времени в свой вывод
  • запись в разные файлы, по одному на каждый процесс MPI
  • объединить их вместе, отсортировав по отметке времени
person Jens Gustedt    schedule 21.10.2011

Я не уверен, что полностью понимаю вашу проблему... может помочь добавление вывода кода к вашему вопросу.

Что я могу сказать точно, так это то, что MPI_Send и MPI_Recv определенно являются блокирующими функциями. Вы пытались вместо этого использовать неблокирующие функции (например, MPI_Isend и MPI_Irecv)? Если да, то решило ли это вашу проблему?

person Bertrand Moreau    schedule 21.10.2011
comment
Я добавил вывод. Я не использовал неблокирующую отправку и получение, потому что мне нужна функция блокировки - person CuriousCoder; 21.10.2011
comment
Спасибо за добавление вывода. Я согласен с Jens и user786653, ваша проблема, скорее всего, связана с порядком печати, а не с вашей реализацией. - person Bertrand Moreau; 21.10.2011