2017-04-14 70 views
1

說我有n個過程:如何獲得MPI中的所有等級來發送一個值爲0,然後在所有等級上進行阻止接收?

他們做一個計算,然後發送結果排名爲0。這是我希望發生的:

等級0將等待,直到它從結果所有的隊伍,然後加起來

我該怎麼做?另外,我想避免以下內容:

例如, 4個進程P0,P1,P2,P3,

P1 -> P0 
P2 -> P0 
P3 -> P0 

與此同時P1已完成其計算等P1-> P0再次發生。

我希望P0只在一個週期內完成3個過程的添加,然後再爲下一個週期做3個過程

有人可以建議一個MPI功能來做到這一點?我知道MPI_Gather,但我不知道它阻擋

我想過了這個:

#include <mpi.h> 
#include <stdio.h> 

int main() 
{ 
int pross, rank,p_count = 0; 
int count = 10; 
MPI_Init(&argc,&argv); 
MPI_Comm_size(MPI_COMM_WORLD,&pross); 
MPI_Comm_rank(MPI_COMM_WORLD,&rank); 

int * num = malloc((pross-1)*sizeof(int)); 

     if(rank !=0) 
     { 
      MPI_Send(&count,1,MPI_INT,0,1,MPI_COMM_WORLD); 
     } 
     else 
     {    
      MPI_Gather(&count, 1,MPI_INT,num, 1, MPI_INT, 0,MPI_COMM_WORLD); 
      for(ii = 0; ii < pross-1;ii++){printf("\n NUM %d \n",num[ii]); p_count += num[ii]; } 
} 
MPI_Finalize(); 
} 

我收到提示:

*** Process received signal *** 
    Signal: Segmentation fault (11) 
    Signal code: Address not mapped (1) 
    Failing at address: (nil) 
    [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11630)[0x7fb3e3bc3630] 
    [ 1] /lib/x86_64-linux-gnu/libc.so.6(+0x90925)[0x7fb3e387b925] 
    [ 2] /usr/lib/libopen-pal.so.13(+0x30177)[0x7fb3e3302177] 
    [ 3] /usr/lib/libmpi.so.12(ompi_datatype_sndrcv+0x54c)[0x7fb3e3e1e3ec] 
    [ 4] /usr/lib/openmpi/lib/openmpi/mca_coll_tuned.so(ompi_coll_tuned_gather_intra_basic_linear+0x143)[0x7fb3d53d9063] 
    [ 5] /usr/lib/libmpi.so.12(PMPI_Gather+0x1ba)[0x7fb3e3e29a3a] 
    [ 6] sosuks(+0xe83)[0x55ee72119e83] 
    [ 7] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7fb3e380b3f1] 
    [ 8] sosuks(+0xb5a)[0x55ee72119b5a] 
    *** End of error message *** 

而且,我想:

#include <mpi.h> 
#include <stdio.h> 

int main() 
{ 
int pross, rank,p_count = 0; 
int count = 10; 
MPI_Init(&argc,&argv); 
MPI_Comm_size(MPI_COMM_WORLD,&pross); 
MPI_Comm_rank(MPI_COMM_WORLD,&rank); 

int * num = malloc((pross-1)*sizeof(int)); 

     if(rank !=0) 
     { 
      MPI_Send(&count,1,MPI_INT,0,1,MPI_COMM_WORLD); 
     } 
     else 
     {    
      MPI_Gather(&count, 1,MPI_INT,num, 1, MPI_INT, 0,MPI_COMM_WORLD); 
      for(ii = 0; ii < pross-1;ii++){printf("\n NUM %d \n",num[ii]); p_count += num[ii]; } 
} 
MPI_Finalize(); 
} 

我得到錯誤的位置:

*** Process received signal *** 
    Signal: Segmentation fault (11) 
    Signal code: Address not mapped (1) 
    Failing at address: 0x560600000002 
    [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11630)[0x7fefc8c11630] 
    [ 1] mdscisuks(+0xeac)[0x5606c1263eac] 
    [ 2] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7fefc88593f1] 
    [ 3] mdscisuks(+0xb4a)[0x5606c1263b4a] 
    *** End of error message *** 

對於第二次嘗試,這裏需要注意的是send和recv是成功的,但根由於某些原因只能從隊列中接收2條消息。看到的分段錯誤是由於在num中只有兩個元素,我不明白爲什麼只接收兩次

我打電話的代碼

mpiexec -n 6 ./sosuks 

有人能告訴我去實現我的想法更好的/正確的方法是什麼?

UPDATE:

除了回答以下,我發現我在執行錯誤上面,我想和大家分享:

#include <mpi.h> 
#include <stdio.h> 

int main() 
{ 
int pross, rank,p_count = 0; 
int count = 10; 
MPI_Init(&argc,&argv); 
MPI_Comm_size(MPI_COMM_WORLD,&pross); 
MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
MPI_Status status; 
int * num = malloc((pross-1)*sizeof(int)); 

     if(rank !=0) 
     { 
      MPI_Send(&count,1,MPI_INT,0,1,MPI_COMM_WORLD); 
     } 
     else 
     { 
     int var,lick = 0; 
     for(lick = 1; lick < pross; u++) 
     { 
     int fetihs; 
     MPI_Recv(&fetihs,1,MPI_INT,lick,1,MPI_COMM_WORLD,&status);   

     var += fetihs; 
     } 
    // do things with var 
} 
MPI_Finalize(); 
} 
+2

如果將所有結果相加,那麼您可能需要'MPI_Reduce',而不是'MPI_Gather'。 – Sneftel

+0

但是它會按照上面問題中概述的阻塞過程嗎?我試圖在所有過程達到某個特定點後才進行添加。在某種程度上,我試圖「同步」來自該步驟的所有進程的結果。 – user26763

+0

你的描述不是很清楚,但它聽起來像你想要每一輪的障礙。是的,會有障礙(沒有合理的方法來減少)。 – Sneftel

回答

1

在你的情況下,作爲Sneftel指出的那樣,你需要MPI_Reduce。另外,在循環完成之前,您不需要顯式同步。

#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char* argv[]) 
{ 
    int pross, rank, p_count, count = 10; 

    MPI_Init(&argc,&argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &pross); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    int* num = malloc((pross-1)*sizeof(int)); 

    // master does not send data to itself. 
    // only workers send data to master. 

    for (int i=0; i<3; ++i) 
    { 
     // to prove that no further sync is needed. 
     // you will get the same answer in each cycle. 
     p_count = 0; 

     if (rank == 0) 
     { 
      // this has not effect since master uses p_count for both 
      // send and receive buffers due to MPI_IN_PLACE. 
      count = 500; 

      MPI_Reduce(MPI_IN_PLACE, &p_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); 
     } 
     else 
     { 
      // for slave p_count is irrelevant. 
      MPI_Reduce(&count, NULL, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); 
     } 

     if (rank == 0) 
     { 
      printf("p_count = %i\n", p_count); 
     } 

     // slaves send their data to master before the cycle completes. 
     // no need for explicit sync such as MPI_Barrier. 
     // MPI_Barrier(MPI_COMM_WORLD); // no need. 
    } 

    MPI_Finalize(); 
} 

在從站上述count的代碼在主減少到p_count。請注意0​​和兩個MPI_Reduce調用。只需簡單地設置count = 0並呼叫MPI_Reduce按照所有級別,您就可以獲得相同的功能,而不需要MPI_IN_PLACE

for (int i=0; i<3; ++i) 
{ 
    p_count = 0;  
    if (rank == 0) count = 0; 

    MPI_Reduce(&count, &p_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);   
} 
相關問題