2011-10-21 132 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是阻塞函數。但是,有時它不會那樣表現

編輯:這是一個示例輸出,其中出現競態條件。正如你所看到的,即使在1發送消息之前,0收到的消息(來自1的「1抵達屏障」)。

0是第1輪

0接收的獲勝者:1到達巴里

0 2輪

1的贏家是圓的失敗者1

1發送到達味精

2是第1輪的優勝者

2接收:3到達巴里

2是第2輪

2發送到達味精

3的輸家是圓的1

3發送到達味精

的輸

0收到:2抵達巴里

0發送喚醒信息msg

0發送喚醒味精

1接收:喚醒MSG從0附有標籤在第1輪

2接收:喚醒MSG從0附有標籤在第2輪

2發送喚醒味精

3收到:來自2的喚醒信息,第2輪帶有標籤

+0

通過競爭條件,我的意思是接收過程即使在發送過程發送之前也會收到消息! – CuriousCoder

+0

你的程序違反因果關係是不太可能的。你只是以這種方式看到*打印*。 IIRC MPI(儘管它可能取決於實現)是否在進程0上打印所有內容,這意味着進程1上的「printf」實際上將其數據發送給進程0打印。 – user786653

+0

@ user786653:我實際上正在運行此代碼同一臺機器。我被分配了一組機器。如果我在集羣的不同機器上分發代碼並運行該程序,該怎麼辦? printf語句是否仍然會被髮送到進程0進行打印? – CuriousCoder

回答

1

爲了調試mpi程序,打印語句通常不是一個很好的解決方案。由於打印統計信息需要通過網絡從不同節點發送到控制檯並在之前進行緩存。

要調試它,你應該讓每個處理器寫入一個自己的輸出文件。或者讓只有一個處理器打印語句,其中您使用std :: cerr禁用緩存,或者以某種方式禁用printf的緩存。

0

我不知道我完全理解您的問題...將代碼的輸出添加到您的問題可能會有所幫助。

我可以肯定地說,MPI_Send和MPI_Recv絕對是阻塞函數。您是否嘗試過使用非阻塞函數(即MPI_Isend和MPI_Irecv)?如果是的話,它解決了你的問題嗎?

+0

我已經添加了輸出。我沒有使用非阻塞發送和接收bcoz我需要阻止功能 – CuriousCoder

+0

謝謝你添加輸出。我同意Jens和user786653的觀點,你的問題更可能與打印順序相關,而不是與你的實現相關。 –

2

以我的經驗,你很可能有一個觀察問題,而不是你的基礎算法。通常在這種環境下,printf只是無序到達。你會根據自己的時間戳必須

  • 放時間戳在輸出
  • 寫入不同的文件,每個每個MPI進程
  • 它們合併一個重新走到一起通過排序