2011-12-01 3 views
3

나는 여러 프로세스에 의해 병렬로 조작되는 2D 배정 밀도 배열을 가지고 있습니다. 각 프로세스는 배열의 일부를 조작하고 모든 반복이 끝날 때마다 모든 프로세스에 2D 배열의 동일한 복사본이 있는지 확인해야합니다.MPI 브로드 캐스트 2D 배열

크기 10 * 10 및 2 개의 프로세스 (또는 프로세서)의 배열을 가정합니다. 프로세스 1 (P1)은 2D 행의 첫 번째 5 개 행 (5 * 10 = 50 개 요소)을 조작하고 P2는 마지막 5 개 행 (총 50 개 요소)을 조작합니다. 그리고 각 반복 끝에 P1이 있어야합니다. (ITS 고유의 처음 5 행 + P2의 마지막 5 행). P2는 (P1의 첫 번째 5 행 + 마지막 5 행의 길이) 있어야합니다. 시나리오가 명확하길 바란다.

아래 주어진 코드를 사용하여 브로드 캐스트하려고합니다. 그러나 내 프로그램은이 오류로 종료됩니다 : "응용 프로그램이 종료 된 문자열로 종료되었습니다 : 응답 (신호 1)".

Jonathan의 MPI_Bcast a dynamic 2d array은 이미 여기에 지적한 바와 같이 인접한 2D 메모리 할당자를 사용하고 있습니다. 하지만 여전히 같은 오류가 발생합니다.

누군가 나를 도울 수 있습니까?

내 코드 :

double **grid, **oldgrid; 
int gridsize; // size of grid 
int rank, size; // rank of current process and no. of processes 
int rowsforeachprocess, offset; // to keep track of rows that need to be handled by each process 

/* allocation, MPI_Init, and lots of other stuff */ 

rowsforeachprocess = ceil((float)gridsize/size); 
offset = rank*rowsforeachprocess; 

/* Each process is handling "rowsforeachprocess" #rows. 
* Lots of work done here 
* Now I need to broadcast these rows to all other processes. 
*/ 

for(i=0; i<gridsize; i++){ 
    MPI_Bcast(&(oldgrid[i]), gridsize-2, MPI_DOUBLE, (i/rowsforeachprocess), MPI_COMM_WORLD); 
} 

제 2 부 : 위의 코드는 1D 분해를 사용하여 라플라스 방정식에 대한 병렬 솔버의 일부이며 나는 마스터 노동자 모델을 사용하지 않았다. 마스터 - 작업자 모델을 사용하면 코드가 더 쉬워 집니까?

답변

2

여기서 발생하는 충돌 문제는 2 차원 배열 포인터 문제입니다. & (oldgrid [i])은 double 형 포인터가 아니라 double 형 포인터입니다. 포인터는 포인터를 가리 킵니다. 배열의 i 행이 아니라 배열의 i 행이됩니다. MPI_Bcast(&(oldgrid[i][0]),.. 또는 MPI_Bcast(oldgrid[i],...이 필요합니다.

이렇게하려면 행마다 하나씩 값 비싼 공동 커뮤니 케 이터 만 사용하는 다른 방법이 있습니다. 모든 사람에게 전체 배열의 복사본이 필요하면 MPI_Allgather을 사용하여 데이터를 모아서 모든 사람에게 배포 할 수 있습니다. 또는 프로세스에 동일한 수의 행이없는 일반적인 경우에는 MPI_Allgatherv입니다. 대신 방송을 통해 루프의,이 보일 것이다 조금 같은 : 카운트 각 작업에 의해 전송 된 항목의 수, 그리고 displs는 변위이다

{ 
    int *counts = malloc(size*sizeof(int)); 
    int *displs = malloc(size*sizeof(int)); 
    for (int i=0; i<size; i++) { 
     counts[i] = rowsforeachprocess*gridsize; 
     displs[i] = i*rowsforeachprocess*gridsize; 
    } 
    counts[size-1] = (gridsize-(size-1)*rowsforeachprocess)*gridsize; 

    MPI_Allgatherv(oldgrid[offset], mynumrows*gridsize, MPI_DOUBLE, 
        oldgrid[0],  counts, displs, MPI_DOUBLE, MPI_COMM_WORLD); 
    free(counts); 
    free(displs); 
} 

.

하지만 마침내 모든 프로세스가 전체 배열의 사본을 가지고 있어야합니까? 라 플라 시안을 계산하는 중이라면 배열 전체가 아닌 인접한 행만 있으면됩니다. 난 그냥 MPI_Bcast 자신의 포인터가 주소와 문제를 파악

int main(int argc, char**argv) { 
double **oldgrid; 
const int gridsize=10; // size of grid 
int rank, size;  // rank of current process and no. of processes 
int rowsforeachprocess; // to keep track of rows that need to be handled by each process 
int offset, mynumrows; 
MPI_Status status; 

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

rowsforeachprocess = (int)ceil((float)gridsize/size); 
offset = rank*rowsforeachprocess; 
mynumrows = rowsforeachprocess; 
if (rank == size-1) 
    mynumrows = gridsize-offset; 

rowsforeachprocess = (int)ceil((float)gridsize/size); 
offset = rank*rowsforeachprocess; 
mynumrows = rowsforeachprocess; 
if (rank == size-1) 
    mynumrows = gridsize-offset; 

malloc2ddouble(&oldgrid, mynumrows+2, gridsize); 

for (int i=0; i<mynumrows+2; i++) 
    for (int j=0; j<gridsize; j++) 
     oldgrid[i][j] = rank; 

/* exchange row data with neighbours */ 
int highneigh = rank+1; 
if (rank == size-1) highneigh = 0; 

int lowneigh = rank-1; 
if (rank == 0) lowneigh = size-1; 

/* send data to high neibhour and receive from low */ 

MPI_Sendrecv(oldgrid[mynumrows], gridsize, MPI_DOUBLE, highneigh, 1, 
      oldgrid[0],   gridsize, MPI_DOUBLE, lowneigh, 1, 
      MPI_COMM_WORLD, &status); 

/* send data to low neibhour and receive from high */ 

MPI_Sendrecv(oldgrid[1],   gridsize, MPI_DOUBLE, lowneigh, 1, 
      oldgrid[mynumrows+1], gridsize, MPI_DOUBLE, highneigh, 1, 
      MPI_COMM_WORLD, &status); 


for (int proc=0; proc<size; proc++) { 
    if (rank == proc) { 
     printf("Rank %d:\n", proc); 
     for (int i=0; i<mynumrows+2; i++) { 
      for (int j=0; j<gridsize; j++) { 
       printf("%f ", oldgrid[i][j]); 
      } 
      printf("\n"); 
     } 
     printf("\n"); 
    } 
    MPI_Barrier(MPI_COMM_WORLD); 
} 
+0

: 같은

이 보일 것이다. :) 하지만 Allgather 명령을 가르쳐 주셔서 감사합니다. 또한 이웃 한 프로세스에서 단 하나의 행만 필요로하는 모든 프로세스에 대해 여러분이 말하는 것은 많은 의미가 있습니다! 나는 그것을 시도 할 것이다. – Neo