2011-10-21 6 views
2

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 : 다음은 경쟁 조건이 발생하는 샘플 출력입니다. 보시다시피, 1은 메시지를 보내기 전에도 1에서 메시지 ("1은 장벽에 도착 함")를 받았습니다.

0

0 수신 라운드의 승자는 1이 배리

0에 도달되는 2 라운드

1 승자 라운드 패자 1

1 도달 범위 메시지

2가 1 라운드의 승자입니다.

수신 : 3 라운드 2

2 전송 도달 MSG

3 패자 1 라운드

3 송신 도달 MSG

의 패자 인 배리

2 도착

수신 됨 : 2 배럴에 도착 함

0 깨우기 송신 msg

01 23,516,

0

1 수신 된 웨이크 업 MSG 전송 : 1 라운드

2에서 태그와 0에서 웨이크 업 MSG받은 : 웨이크 업 MSG를 0 태그 라운드 2

2에서 웨이크 업 MSG를 전송

3 수신 : 1에서 태그를 사용하여 2에서 웨이크 업 메시지

+0

경쟁 조건에 따라, 내가받는 의미는 수신 프로세스가 프로세스를 보내기 전에도 메시지를 수신한다는 것입니다. – CuriousCoder

+0

프로그램이 위반 인과 관계라는 것은 거의 없습니다. 당신은 단지 그것을 * 인쇄 된 그대로보고있는 것입니다. IIRC MPI (구현에 따라 다르 겠지만)는 프로세스 0에서 인쇄하는 모든 작업을 수행합니다. 즉, 프로세스 1의 "printf"는 실제로 프로세스 0에서 인쇄하기 위해 데이터를 보냅니다. – user786653

+0

@ user786653 : 실제로이 코드는 같은 기계. 컴퓨터 클러스터가 할당되었습니다. 클러스터의 다른 시스템에 코드를 배포하고 프로그램을 실행하면 어떻게됩니까? printf 문은 여전히 ​​인쇄를 위해 프로세스 0으로 전송됩니까? – CuriousCoder

답변

1

mpi 프로그램을 디버깅 할 때 print 문은 일반적으로 좋은 해결책이 아닙니다. 인쇄 문구는 네트워크를 통해 다른 노드에서 콘솔로 보내야하며 이전에 캐싱됩니다.

디버깅하려면 각 프로세서가 자체 출력 파일에 기록하도록해야합니다. 또는 하나의 프로세서 만 std :: cerr을 사용하여 캐싱을 비활성화하거나 printf의 캐싱을 비활성화하는 명령문을 인쇄 할 수 있습니다.

0

귀하의 문제를 완전히 이해하고 있는지 확실하지 않습니다 ... 귀하의 질문에 코드 출력을 추가하는 것이 도움이 될 수 있습니다.

제가 말할 수있는 것은 MPI_Send와 MPI_Recv가 확실히 기능을 차단하고 있다는 것입니다. 대신 비 차단 기능 (예 : MPI_Isend 및 MPI_Irecv)을 사용해 보셨습니까? 그렇다면 문제가 해결 되었습니까?

+0

출력을 추가했습니다. 비 차단을 사용하지 않고 bcoz를 수신했습니다. 기능을 차단해야합니다. – CuriousCoder

+0

출력을 추가해 주셔서 감사합니다. Jens와 user786653에 동의합니다. 문제는 구현보다는 인쇄 명령과 관련이 있습니다. –

2

내 경험에 비추어 볼 때 관찰 알고리즘에는 문제가있을 가능성이 높습니다. 일반적으로 이러한 설정의 printf은 단순히 순서가 잘못되었습니다.당신은 당신의 타임 스탬프에 따라 정렬하여 다시 함께 당신의 출력에 다른 파일에

  • 쓰기, 각 MPI 과정
  • 병합에 하나씩
    • 에 넣어 타임 스탬프이있을 것이다