2012-03-16 2 views
4

나는 각 프로세스가 자신의 서브 매트릭스를 가지고있는 3D 매트릭스에서 작동하는 병렬 코드를 작성하려고하지만, 자신의 작업을 수행하기 위해 이웃 프로세스의 서브 매트릭스 (경계 평면)에 대한 정보가 필요하다. 이러한 정보를 지점 간 통신으로 보내지 만 대형 매트릭스의 경우 좋은 생각이 아니므로 파생 데이터 유형을 통신에 사용하기로 결정했습니다. 나는 mpi_type_vector에 문제가 예를 들어 나는 NX*NY*NZ 매트릭스를 가지고 있고 나는이 일을 다음과 같은 행 쓰기 다른 프로세스에 일정 NY와 비행기를 보낼 :3D 배열에 MPI 파생 데이터 형식을 사용하는 방법은 무엇입니까?

MPI_Datatype sub; 

MPI_Type_vector(NX, NZ, NY*NZ, MPI_DOUBLE, &sub); 

MPI_Type_commit(&sub); 

을하지만 보낼 수 없습니다 (작동하지 않습니다 내 원하는 비행기). 뭐가 잘못 되었 니? 내 테스트 코드는 여기에 있습니다 : 3 차원 매트릭스와

#include <mpi.h> 
#include <iostream> 

using namespace std; 

int main(int argc,char ** argv) 
{ 

    int const IE=100,JE=25,KE=100; 
    int size,rank; 
    MPI_Status status; 

    MPI_Init(&argc,&argv); 
    MPI_Comm_size(MPI_COMM_WORLD,&size); 
    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
    MPI_Datatype sub; 
    MPI_Type_vector(KE,IE,IE+(JE-1)*IE,MPI_DOUBLE,&sub); 
    MPI_Type_commit(&sub); 

    if (rank==0){ 

     double*** a=new double**[IE]; 

     for(int i=0;i<IE;i++){ 
      a[i]=new double *[JE]; 
      for(int j=0;j<JE;j++){ 
       a[i][j]=new double [KE]; 
      } 
     } 

     for(int i=0;i<IE;i++){ 
      for(int j=0;j<JE;j++){ 
       for(int k=0;k<KE;k++){ 
        a[i][j][k]=2; 
       }}} 

     for(int i=0;i<IE;i++){ 
      for(int j=0;j<JE;j++){ 
       a[i][j][0]=2; 
      }} 

     MPI_Send(&a[0][0][0],1,sub,1,52,MPI_COMM_WORLD); 

    } 

    if (rank==1){ 

     double*** b=new double**[IE]; 

     for(int i=0;i<IE;i++){ 
      b[i]=new double *[JE]; 
      for(int j=0;j<JE;j++){ 
       b[i][j]=new double [KE]; 
      } 
     } 

     for(int i=0;i<IE;i++){ 
      for(int j=0;j<JE;j++){ 
       for(int k=0;k<KE;k++){ 
        b[i][j][k]=0; 
       }}} 

     MPI_Recv(&b[0][0][0][0],1,sub,0,52,MPI_COMM_WORLD,&status); 

     for(int i=0;i<IE;i++){ 
      for(int j=0;j<JE;j++){ 
       for(int k=0;k<KE;k++){ 
        if(b[i][j][k]>0){ 
         cout<<"b["<<i<<"]["<<j<<"]["<<k<<"]="<<b[i][j][k]<<endl; 
        }}}} 

    } 

    MPI_Finalize(); 

} 

답변

7

, 당신이 (이 참여 진전이 있기 때문에) 벡터의 벡터를 사용해야 할 것 일반적으로 - 가능하지만, 훨씬 간단을 사용하는 것입니다 MPI_Type_create_subarray()을 사용하면 원하는 다차원 배열의 슬래브를 조각 낼 수 있습니다.

업데이트 : 위의 코드에서 하나의 문제는 할당 한 3D 배열이 연속적이지 않다는 것입니다. 그것은 IE * JE의 모음입니다. 서로 가까이있을 수도 있고 그렇지 않을 수도 있습니다. 따라서 데이터 평면을 추출 할 수있는 확실한 방법은 없습니다.

당신은 같은 것을 할 필요가 :

double ***alloc3d(int l, int m, int n) { 
    double *data = new double [l*m*n]; 
    double ***array = new double **[l]; 
    for (int i=0; i<l; i++) { 
     array[i] = new double *[m]; 
     for (int j=0; j<m; j++) { 
      array[i][j] = &(data[(i*m+j)*n]); 
     } 
    } 
    return array; 
} 

당신이 기대하는 것 같은 그런 다음 데이터는 가리키는 포인터의 배열, 하나 개의 큰 큐브입니다. C가 진정한 다차원 배열을 가지고 있지 않다는 사실은 항상 C + MPI로 나타납니다.

+0

... 난 그보다 더 많은 정보가 필요합니다. 무엇을 시도 했습니까? 어떻게 문제가 있습니까? –

+0

int a_size [3] = {100,25,100}; int subside [3] = {100,1,100}; int start [3] = {0,0,0}; int order = 1; MPI_Type_create_subarray (3, asside, sideside, start, order, MPI_DOUBLE, &sub); (100 * 25 * 100 행렬을 가지고 있고 일정한 NY에서 한 프로세스에서 다른 프로세스로 평면을 보내려합니다) 위의 코드는 배열의 다른 구성 요소를 전송합니다. 내 원하는 비행기 – peaceman

+0

어떻게 송수신 전화합니까?그리고 주문은 MPI_ORDER_C가되어야한다. 1은 아니지만 2 가지가 특정 임 플 레이션에 대해 동일 할 수도있다. –

0

Jonathan Dursi에게 감사드립니다. 여기서는 3d 행렬을 생성하고 통신을 위해 파생 데이터 유형을 사용하는 완전한 코드를 게시하고자합니다 (하나의 프로세스에서 다른 프로세스로 상수 y가있는 평면 만 전송 됨). 위에 게시 된 Jonathan Dursi의 기능을 사용했습니다.

#include <mpi.h> 
#include <iostream> 
#include <math.h> 
#include <fstream> 
#include <vector> 
using namespace std; 
#define IE 100 
#define JE 50 
#define KE 100 

#define JE_loc 52 
double ***alloc3d(int l, int m, int n) { 
double *data = new double [l*m*n]; 
double ***array = new double **[l]; 
for (int i=0; i<l; i++) { 
    array[i] = new double *[m]; 
    for (int j=0; j<m; j++) { 
     array[i][j] = &(data[(i*m+j)*n]); 
    } 
} 
return array; 
} 




int main(int argc ,char ** argv) 
{ 
//////////////////////declartion///////////////////////////// 
int const NFREQS=100,ia=7,ja=7,ka=7; 
double const pi=3.14159; 
int i,j,size,rank,k; 
//MPI_Status status[10]; 
MPI_Status status; 
MPI_Request request[10]; 
MPI_Init(&argc, &argv); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Datatype sub; 
MPI_Type_vector(KE,IE,IE+(JE-1)*IE,MPI_DOUBLE,&sub); 
MPI_Type_commit(&sub); 


double ***a=alloc3d(IE,JE,KE); 
for (i=0; i<IE; i++) { 
    for (j=0; j<JE; j++) { 
     for (k=0; k<KE; k++) { 
      a[i][j][k]=0.0; 
     } 
    } 
} 
if (rank==0) { 
    for (i=0; i<IE; i++) { 
     for (j=0; j<JE; j++) { 
      for (k=0; k<KE; k++) { 
       a[i][j][k]=2; 
      } 
     } 
    } 
    MPI_Send(&a[0][0][0],1,sub,1,52,MPI_COMM_WORLD); 

} 
if (rank==1) { 
    MPI_Recv(&a[0][49][0],1,sub,0,52,MPI_COMM_WORLD,&status); 
    for (i=0; i<IE; i++) { 
     for (j=0; j<JE; j++) { 
      for (k=0; k<KE; k++) { 
       if (a[i][j][k]>0) { 
        cout<<"a["<<i<<"]["<<j<<"]["<<k<<"]="<<a[i][j][k]<<endl; 
       } 
      } 
     } 
    } 

} 
MPI_Finalize(); 
} 
1

검토 된 코드가 여전히 올바르게 작동하지 않는다고 말씀 드려서 죄송합니다. 출력이 올바른 이유는 IE와 KE가 동일하기 때문입니다. 그 값이 다르다면 값이 Y- 색인을 번갈아 쓰는 것을 볼 수 있습니다.

당신은 같다 조나단 더스트의 코드 샘플의 메모리 할당에 대해 살펴있는 경우 :

[x0y0z0] [x0y0z1] [x0y1z0] [x0y1z1] [x1y0z0] [x1y0z1] [x1y1z0] [x1y1z1] //or 
{x0:(y0:[z0,z1]) ; (y1:[z0,z1])} ; {x1:(y0:[z0,z1]) ; (y1:[z0,z1])} //nx=ny=nz=2 
     <bl.len> 
X    count    X 
    |<-   stride    ->| 
당신이 뉴질랜드 값의 blocklength 당신은 NX 블록의 수를 가지고 볼 수

과를 ny * nz의 그들 사이에 걸음마.

당신이 당신의 데이터 유형을 변경하는 경우 귀하의 코드가 제대로 작동 :

MPI_Type_vector(IE,KE,KE*JE,MPI_DOUBLE,&sub); 
+0

네 말이 맞아, 이건 잘못된거야. 귀하의 회신에 감사드립니다. – peaceman

관련 문제