2012-12-13 46 views
25

到目前为止,我的应用程序正在阅读一个带有整数列表的txt文件。这些整数需要由主进程(即具有等级0的处理器)存储在数组中。这工作正常。从C中如何使用MPI_Scatter和MPI_Gather?

现在,当我运行程序时,我有一条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,和许多其他人)是集体操作;他们必须通过全部调用通信器中的任务。通信器中的所有处理器进行相同的调用,并执行操作。 (这就是为什么分散和收集都需要作为参数之一的“根”过程,其中所有数据都来自/来自)。通过这样做,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