2012-12-13 2 views
25

지금까지, 내 ​​응용 프로그램은 정수 목록과 함께 txt 파일을 읽고 있습니다. 이러한 정수는 마스터 프로세스, 즉 순위가 0 인 프로세서에 의해 배열에 저장되어야합니다. 정상적으로 작동합니다.C에서 MPI_Scatter 및 MPI_Gather를 어떻게 사용합니까?

이제 프로그램을 실행할 때 master 프로세스인지 여부를 확인하는 if 문이 있으며 그럴 경우 MPI_Scatter 명령을 실행하고 있습니다.

내가 이해하는 바로는이 배열을 숫자로 세분화하여 슬레이브 프로세스, 즉 순위> 0 인 모든 것으로 전달합니다. 그러나 MPI_Scatter을 어떻게 처리해야할지 모르겠습니다. 어떻게 슬레이브 프로세스가 서브 어레이를 얻기 위해 "가입"합니까? 마스터가 아닌 프로세스에게 서브 어레이로 어떤 일을하도록 어떻게 말할 수 있습니까?

마스터 프로세스가 배열의 요소를 보내는 방법을 보여주는 간단한 예제를 제공 한 다음 슬레이브에 합계를 더하고이를 마스터에 반환하면 합계가 모두 합쳐져서 출력됩니다. 지금까지

내 코드 :

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

//A pointer to the file to read in. 
FILE *fr; 

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

int rank,size,n,number_read; 
char line[80]; 
int numbers[30]; 
int buffer[30]; 

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

fr = fopen ("int_data.txt","rt"); //We open the file to be read. 

if(rank ==0){ 
printf("my rank = %d\n",rank); 

//Reads in the flat file of integers and stores it in the array 'numbers' of type int. 
n=0; 
while(fgets(line,80,fr) != NULL) { 
    sscanf(line, "%d", &number_read); 
    numbers[n] = number_read; 
    printf("I am processor no. %d --> At element %d we have number: %d\n",rank,n,numbers[n]); 
    n++; 
} 

fclose(fr); 

MPI_Scatter(&numbers,2,MPI_INT,&buffer,2,MPI_INT,rank,MPI_COMM_WORLD); 

} 
else { 
MPI_Gather (&buffer, 2, MPI_INT, &numbers, 2, MPI_INT, 0, MPI_COMM_WORLD); 
printf("%d",buffer[0]); 
} 
MPI_Finalize(); 
return 0; 
} 

답변

56

이 작업이 새로운 사람들과 MPI 작동 방법에 대한 일반적인 오해이다; 특히 공동 작업에서 사람들이 0 번에서 방송 (MPI_Bcast)을 사용하려고 시도 할 때 호출이 어떻게 든 다른 프로세서에 데이터를 "푸시"할 것으로 기대합니다. 하지만 이것이 MPI 루틴이 실제로 작동하는 방식은 아닙니다. 대부분의 MPI 통신은 발신자와 수신자 모두 MPI 호출을해야합니다.

특히

, MPI_Scatter()MPI_Gather() (MPI_Bcast하고, 그리고 많은 다른) 집단 동작이고; Communicator의 작업 중 에 의해 호출되어야합니다. 커뮤니케이터의 모든 프로세서가 동일한 호출을하고 작업이 수행됩니다. (분산 및 수집 모두가 모든 데이터가 /에서 오는 "루트"프로세스의 매개 변수 중 하나로 필요합니다.) 이러한 방식으로 MPI 구현은 통신 패턴을 최적화 할 수있는 많은 범위를 가지고 있습니다.

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

int main(int argc, char **argv) { 
    int size, rank; 

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

    int *globaldata=NULL; 
    int localdata; 

    if (rank == 0) { 
     globaldata = malloc(size * sizeof(int)); 
     for (int i=0; i<size; i++) 
      globaldata[i] = 2*i+1; 

     printf("Processor %d has data: ", rank); 
     for (int i=0; i<size; i++) 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 

    MPI_Scatter(globaldata, 1, MPI_INT, &localdata, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    printf("Processor %d has data %d\n", rank, localdata); 
    localdata *= 2; 
    printf("Processor %d doubling the data, now has %d\n", rank, localdata); 

    MPI_Gather(&localdata, 1, MPI_INT, globaldata, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    if (rank == 0) { 
     printf("Processor %d has data: ", rank); 
     for (int i=0; i<size; i++) 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 

    if (rank == 0) 
     free(globaldata); 

    MPI_Finalize(); 
    return 0; 
} 

가 제공 실행 :

gpc-f103n084-$ mpicc -o scatter-gather scatter-gather.c -std=c99 
gpc-f103n084-$ mpirun -np 4 ./scatter-gather 
Processor 0 has data: 1 3 5 7 
Processor 0 has data 1 
Processor 0 doubling the data, now has 2 
Processor 3 has data 7 
Processor 3 doubling the data, now has 14 
Processor 2 has data 5 
Processor 2 doubling the data, now has 10 
Processor 1 has data 3 
Processor 1 doubling the data, now has 6 
Processor 0 has data: 2 6 10 14 
+2

어떤 훌륭한 대답

그래서 여기 (수집 포함 업데이트 ) 간단한 예입니다. 그것을 아주 똑 바른 앞으로하고 나는 그것이 어떻게 지금 작동하는지 본다. 나는 그것을 집합 적 운영으로 생각하지 않는 실수를했다. 감사합니다. – DSF

+2

와우! 내 하루를 구 했잖아, 건배. 감사합니다. – irobo

+0

대부분의 MPI 소개보다 더 많은 도움이됩니다. – WakaChewbacca

관련 문제