【问题标题】:How are MPI_Scatter and MPI_Gather used from C?如何从 C 中使用 MPI_Scatter 和 MPI_Gather?
【发布时间】:2012-12-01 19:30:34
【问题描述】:

到目前为止,我的应用程序正在读取一个包含整数列表的 txt 文件。这些整数需要由主进程(即等级为 0 的处理器)存储在一个数组中。这工作正常。

现在,当我运行程序时,我有一个 if 语句来检查它是否是主进程,如果是,我正在执行 MPI_Scatter 命令。

据我了解,这将用数字细分数组并将其传递给从属进程,即所有 rank > 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;
}

【问题讨论】:

    标签: c parallel-processing mpi distributed-computing


    【解决方案1】:

    这是一个常见的误解,即 MPI 中的操作如何与刚接触它的人一起工作;特别是在集体操作中,人们尝试从等级 0 开始使用广播 (MPI_Bcast),期望调用以某种方式将数据“推送”到其他处理器。但这并不是 MPI 例程的真正工作方式。大多数 MPI 通信都需要发送方和接收方都进行 MPI 调用。

    特别是,MPI_Scatter()MPI_Gather()(以及 MPI_Bcast 和许多其他)是集体操作;它们必须由通信器中的所有任务调用。通信器中的所有处理器都进行相同的调用,然后执行操作。 (这就是为什么scatter和gather都需要“根”过程作为参数之一,所有数据都来自/来自哪里)。通过这种方式,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
    

    【讨论】:

      猜你喜欢
      • 2017-02-26
      • 2013-10-24
      • 2017-05-25
      • 2020-11-20
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 2011-02-28
      • 1970-01-01
      相关资源
      最近更新 更多