C 中如何使用 MPI_Scatter 和 MPI_Gather? [英] How are MPI_Scatter and MPI_Gather used from C?

查看:30
本文介绍了C 中如何使用 MPI_Scatter 和 MPI_Gather?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So far, my application is reading in a txt file with a list of integers. These integers needs to be stored in an array by the master process i.e. processor with rank 0. This is working fine.

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

Now, when I run the program I have an if statement checking whether it's the master process and if it is, I'm executing the MPI_Scatter command.

据我所知,这将用数字细分数组并将其传递给从属进程,即所有 rank > 0 .但是,我不确定如何处理 MPI_Scatter.slave进程如何订阅"获取子数组?我怎样才能告诉非主进程对子数组做一些事情?

From what I understand this will subdivide the array with the numbers and pass it out to the slave processes i.e. all with rank > 0 . However, I'm not sure how to handle the MPI_Scatter. How does the slave process "subscribe" to get the sub-array? How can I tell the non-master processes to do something with the sub-array?

有人可以提供一个简单的例子来向我展示主进程如何从数组中发送元素,然后让从进程添加总和并将其返回给主进程,主进程将所有总和加在一起并打印出来?

Can someone please provide a simple example to show me how the master process sends out elements from the array and then have the slaves add the sum and return this to the master, which adds all the sums together and prints it out?

到目前为止我的代码:

#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
",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
",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;
}

推荐答案

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

This is a common misunderstanding of how operations work in MPI with people new to it; particularly with collective operations, where people try to start using broadcast (MPI_Bcast) just from rank 0, expecting the call to somehow "push" the data to the other processors. But that's not really how MPI routines work; most MPI communication requires both the sender and the receiver to make MPI calls.

特别是,MPI_Scatter()MPI_Gather()(以及 MPI_Bcast 和许多其他)是集合 操作;它们必须被通信器中的所有 任务调用.通信器中的所有处理器都进行相同的调用,并执行操作.(这就是为什么 scatter 和 gather 都需要根"进程作为参数之一,所有数据都来自/来自那里).通过这种方式,MPI 实现有很大的空间来优化通信模式.

In particular, MPI_Scatter() and MPI_Gather() (and MPI_Bcast, and many others) are collective operations; they have to be called by all of the tasks in the communicator. All processors in the communicator make the same call, and the operation is performed. (That's why scatter and gather both require as one of the parameters the "root" process, where all the data goes to / comes from). By doing it this way, the MPI implementation has a lot of scope to optimize the communication patterns.

这里有一个简单的例子(更新以包括收集):

So here's a simple example (Updated to include gather):

#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("
");
    }

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

    printf("Processor %d has data %d
", rank, localdata);
    localdata *= 2;
    printf("Processor %d doubling the data, now has %d
", 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("
");
    }

    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

这篇关于C 中如何使用 MPI_Scatter 和 MPI_Gather?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆