2013-02-19 14 views
1

我無法將MPI_Isend發送到隨機目標。如果我硬編碼的目的地,它工作正常,但如果我嘗試生成一個隨機的一個它不。下面是一些相關的代碼:MPI_Isend到隨機目標

MPI_Init(&argc,&argv); 
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD,&myid); 
    srand48(myid); 
    request=MPI_REQUEST_NULL; 
    if(myid == 0){ 
      buffer=drand48(); 
      do { 
        destination=lrand48() % numprocs; 
      } while (destination == 0); //Prevent sending to self 
      MPI_Isend(&buffer,1,MPI_DOUBLE,destination,1234,MPI_COMM_WORLD,&request); 

    } 
    else if (myid == destination) { 
      MPI_Irecv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request); 

    } 
    if(myid == 0){ 
      printf("processor %d sent %lf to %d\n",myid,buffer,destination); 
    } 
    else { 
      printf("processor %d got %lf\n",myid,buffer); 
    } 

當我mpirun -np 4 ./a.out運行的程序,我可以編譯只是mpicc main.c罰款輸出爲:

processor 0 sent 0.170828 to 2 
processor 1 got 0.000000 
processor 2 got 0.000000 
processor 3 got 0.000000 

如果我硬編碼目的地爲2,例如,然後我得到預期輸出:

processor 0 sent 0.170828 
processor 1 got 0.000000 
processor 2 got 0.170828 
processor 3 got 0.000000 
+2

'destination'未設置除了0以外的任何等級。有一個很好的機會,沒有處理器會執行Irecv;即使他們這樣做,您在執行Wait之前也會打印結果,因此不能保證在輸出時接收完成。 – 2013-02-19 18:42:11

回答

1

MPI_IsendMPI_Irecv發起相應的非阻塞操作。誰也不能保證他們永遠不會完成你將返回的request手柄從MPI_WaitMPI_Test家庭功能之前(如果使用了測試功能,請求的完成狀態的布爾變量被傳送回來了,它是不是隻要布爾標誌保持爲假就完成)。

雖然您的代碼存在概念性問題。 MPI是一種分佈式內存模式 - 每個MPI等級幾乎住在其獨立的地址空間(雖然不是嚴格的標準要求,這是幾乎所有的MPI實現提供)。因此,在等級0中設置destination不會將其值神奇地轉移到其他進程。您既可以先播出的值或者發送特殊的「空」的消息發送給所有其他的行列,例如:

if (myid == 0) { 
    MPI_Request reqs[numprocs]; 

    buffer=drand48(); 
    do { 
     destination=lrand48() % numprocs; 
    } while (destination == 0); //Prevent sending to self 
    for (i = 1; i < numprocs; i++) { 
     if (i == destination) 
     MPI_Isend(&buffer,1,MPI_DOUBLE,i,1234,MPI_COMM_WORLD,&reqs[i]); 
     else 
     // Send an empty message with different tag 
     MPI_Isend(&buffer,0,MPI_DOUBLE,i,4321,MPI_COMM_WORLD,&reqs[i]); 
    } 
    reqs[0] = MPI_REQUEST_NULL; 
    MPI_Waitall(numprocs, reqs, MPI_STATUSES_IGNORE);  
    printf("processor %d sent %lf to %d\n",myid,buffer,destination); 
} 
else { 
    MPI_Status status; 

    MPI_Recv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status); 
    if (status.MPI_TAG == 1234) 
     printf("processor %d got %lf\n",myid,buffer); 
} 

隨着廣播的代碼是這樣:

request=MPI_REQUEST_NULL; 
if (myid == 0) { 
    buffer=drand48(); 
    do { 
     destination=lrand48() % numprocs; 
    } while (destination == 0); //Prevent sending to self 
    MPI_Bcast(&destination,1,MPI_INT,0,MPI_COMM_WORLD); 
    MPI_Isend(&buffer,1,MPI_DOUBLE,destination,1234,MPI_COMM_WORLD,&request); 
} 
else { 
    MPI_Bcast(&destination,1,MPI_INT,0,MPI_COMM_WORLD); 
    if (myid == destination) { 
     MPI_Irecv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request); 
    } 
} 
MPI_Wait(&request, MPI_STATUS_IGNORE); 
if (myid == 0) { 
    printf("processor %d sent %lf to %d\n",myid,buffer,destination); 
} 
else { 
    printf("processor %d got %lf\n",myid,buffer); 
} 
+0

非常感謝您的幫助 - 現在我明白了,在根進程中設置變量對其他進程中的變量沒有任何作用。 您能解釋在else塊中是否需要MPI_Bcast調用嗎? – user2088217 2013-02-19 20:29:14

+0

@ user2088217,'MPI_Bcast'是一個集體操作 - 它必須由通信器中的所有級別調用才能完成。數據的創建者(MPI_Bcast中的''root'級別)不能簡單地將其推送到其他級別 - 他們必須採取措施來獲取它。 'MPI_Bcast'同時執行push和fetch操作,但是所有等級都必須調用它,所有等級必須指定相同的'root'等級。 – 2013-02-19 21:11:50