2014-03-03 116 views
0

這是LU分解的MPI代碼。LU分解MPI

我已經使用了以下策略 -

有一個大師(等級0)和其他人是奴隸。主站向每個從站發送行。 由於每個從設備可能會接收多於一行,因此我將所有接收的行存儲在一個 緩衝區中,然後對其執行LU分解。這樣做後,我發回 緩衝區的主人。主人不做任何計算。它只是發送和接收。

for(i=0; i<n; i++) 
    map[i] = i%(numProcs-1) + 1; 

for(i=0; i<n-1; i++) 
{ 
    if(rank == 0) 
    { 
     status = pivot(LU,i,n); 

     for(j=0; j<n; j++) 
      row1[j] = LU[n*i+j]; 
    } 

    MPI_Bcast(&status, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    if(status == -1) 
     return -1; 

    MPI_Bcast(row1, n, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

    int tag1 = 1, tag2 = 2, tag3 = 3, tag4 = 4; 

    if(rank == 0) 
    { 
     int pno, start, index, l, rowsReceived = 0; 
     MPI_Request req; 
     MPI_Status stat; 

     for(j=i+1; j<n; j++) 
      MPI_Isend(&LU[n*j], n, MPI_DOUBLE, map[j], map[j], MPI_COMM_WORLD, &req); 

     if(i>=n-(numProcs-1)) 
      cnt++; 

     for(j=0; j<numProcs-1-cnt; j++) 
     { 
      MPI_Recv(&pno, 1, MPI_INT, MPI_ANY_SOURCE, tag2, MPI_COMM_WORLD, &stat); 
      //printf("1. Recv from %d and j : %d and i : %d\n",pno,j,i); 
      MPI_Recv(&rowsReceived, 1, MPI_INT, pno, tag3, MPI_COMM_WORLD, &stat); 
      MPI_Recv(rowFinal, n*rowsReceived, MPI_DOUBLE, pno, tag4, MPI_COMM_WORLD, &stat); 

      /* Will not go more than numProcs anyways */ 
      for(k=i+1; k<n; k++) 
      { 
       if(map[k] == pno) 
       { 
        start = k; 
        break; 
       } 
      } 

      for(k=0; k<rowsReceived; k++) 
      { 
       index = start + k*(numProcs-1); 

       for(l=0; l<n; l++) 
        LU[n*index+l] = rowFinal[n*k+l]; 
      } 
     } 
    } 

    else 
    { 
     int rowsReceived = 0; 
     MPI_Status stat, stats[3]; 
     MPI_Request reqs[3]; 

     for(j=i+1; j<n; j++) 
      if(map[j] == rank) 
       rowsReceived += 1; 


     for(j=0; j<rowsReceived; j++) 
     { 
      MPI_Recv(&rowFinal[n*j], n, MPI_DOUBLE, 0, rank, MPI_COMM_WORLD, &stat); 
     } 

     for(j=0; j<rowsReceived; j++) 
     { 
      double factor = rowFinal[n*j+i]/row1[i]; 

      for(k=i+1; k<n; k++) 
       rowFinal[n*j+k] -= (row1[k]*factor); 

      rowFinal[n*j+i] = factor; 
     } 

     if(rowsReceived != 0) 
     { 
      //printf("Data sent from %d iteration : %d\n",rank,i); 
      MPI_Isend(&rank, 1, MPI_INT, 0, tag2, MPI_COMM_WORLD, &reqs[0]); 
      MPI_Isend(&rowsReceived, 1, MPI_INT, 0, tag3, MPI_COMM_WORLD, &reqs[1]); 
      MPI_Isend(rowFinal, n*rowsReceived, MPI_DOUBLE, 0, tag4, MPI_COMM_WORLD, &reqs[2]); 
     } 
     //MPI_Waitall(3,reqs,stats); 
    } 
} 

我面臨的問題是有時程序掛起。我的猜測是 發送和接收不匹配,但我不能 找出問題所在。

我在大小爲1000x1000,2000x2000,3000x3000,5000x5000, 和7000x7000的矩陣上運行測試用例。 目前代碼掛起爲7000x7000。有人可以幫助 我出去嗎?

注意事項: -

  1. 地圖實現映射方案,該行去哪個奴隸。

  2. rowsReceived告訴每個奴隸它將收到的行數。我不需要 計算,每一次,但我會稍後修復它。

  3. row1是存儲活動行的緩衝區。

  4. rowfinal是正在接收和正在修改的行的緩衝區。

  5. cnt不重要,可以忽略。爲此,需要刪除 rowReceived!= 0的檢查。

回答

0

看起來你從未完成過無阻塞操作。在整個代碼中,你有一堆對MPI_IsendMPI_Irecv的調用,但是你永遠不會做MPI_WaitMPI_Test(或其中一個類似的調用)。沒有完成呼叫,那些非阻塞呼叫將永遠不會完成。

+0

是的。謝謝。我能夠修復它。 –