2017-04-14 18 views
1

내가 n 개의 프로세스를 말해봐 모든 순위와 그 다음 는 그들을까지 더한다.MPI에서 모든 랭크를 얻는 방법은 0을 순위 값으로 보내고 그 다음에 모든 것을 블로킹 받는다. 그것의 결과를 가지고까지 0 <strong></strong>을 기다립니다</p> <p>순위 :</p> <p>그들은 계산을 수행 한 후 0이 순위 결과를 보내 내가 어떻게 할 것입니다 :

어떻게하면됩니까? 또한 다음을 피하고 싶습니다.

예 : 공정 4 P0, P1, P2, P3, P1의 한편에서

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

는 계산이 끝난 등 P1-> P0 다시 일어난다.

P0가 다음 프로세스를 위해 한 번에 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(); 
} 

내가지고있어 오류 :

,536,913,632 10
*** 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에 두 개의 요소 만 있기 때문에 발생했습니다. 이유는 알 수 없습니다. num은 두 번만을 수신합니다.

나는 누군가가 나에게 내 아이디어를 구현하는 더 나은/올바른 방법을 말할 수

mpiexec -n 6 ./sosuks 

로 코드를 호출하는거야?

UPDATE :

외에도 대답에서 내가 공유하고 싶어하는 위 내 구현에서 실수를 발견 아래 : Sneftel가 지적했듯이, 당신은 MPI_Reduce이 필요 귀하의 경우에는

#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_Gather'가 아닌 'MPI_Reduce'가 필요합니다. – Sneftel

+0

그러나 위의 질문에서 설명한대로 차단 절차를 따르시겠습니까? 모든 프로세스가 특정 시점에 도달 한 후에 만 ​​추가를 시도합니다. 어떤면에서는 그 단계에서 모든 프로세스의 결과를 "동기화"하려고합니다. – user26763

+0

설명이 명확하지 않지만 각 라운드의 장벽을 원하는 것처럼 들립니다. 예, 장벽이있을 것입니다. 하나도 없으면 축소 할 수있는 논리적 인 방법이 없습니다. – Sneftel

답변

1

합니다. 또한주기가 완료되기 전에 명시적인 동기화가 필요하지 않습니다. 노예 count 위 코드에서

#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(); 
} 

는 마스터 p_count로 감소된다. MPI_IN_PLACE과 두 번의 MPI_Reduce 호출에 유의하십시오. count = 0을 설정하고 MPI_IN_PLACE없이 모든 순위로 MPI_Reduce을 호출하여 동일한 기능을 사용할 수 있습니다.

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);   
}