使用ScatterV将数组拆分为多个进程 [英] Using ScatterV to split an array to multiple processes

查看:110
本文介绍了使用ScatterV将数组拆分为多个进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MPI,因此必须将数组的一部分发送到不同的进程.例如,考虑3个过程.然后,我需要将红色元素发送给第一个进程,将贪婪元素发送给第二个进程,将黑色元素发送给第三个进程.

I am working with MPI and I have to send parts of an array to different processes. As an example, consider 3 processes. Then I need to send the red elements to the first process, the greed to the second and the black to the third process.

我知道我可以使用Scatterv两次,但是我想最大程度地减少进程与拆分的真实数组之间的通信.有人对我如何做到这一点有建议吗?

I know I could use Scatterv twice, but I want to minimize the communication between processes and the real array that I'm splitting apart is huge. Does anyone have a suggestion on how I can accomplish this?

这是我尝试使用派生数据类型的方法:

Here is my attempt with a derived data type:

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

void print_array(int *array,int n){
    int i;
    printf("\t[");
    for (i=0; i<n; i++) {
        printf(" %d",array[i]);
    }
    printf("]\n");
}

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

int rank,world_size,i,n = 16, block_count = 2;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);

int *array = malloc(n * sizeof(int));
for (i=0; i<n; i++) { array[i]=i;}
if (rank==0) { print_array(array,n);}

int *sendcounts = malloc(world_size * sizeof(int));
int *reccounts = malloc(world_size * sizeof(int));
int *displs = malloc(world_size * sizeof(int));

sendcounts[0]=3; sendcounts[1]=3; sendcounts[2]=2;
displs[0]=0; displs[1]=3; displs[2]=6;

for (i=0; i<world_size; i++) {
    reccounts[i] = sendcounts[i]*block_count;
}

int root = 0;
int *recvbuf = malloc(reccounts[rank] * sizeof(int));
MPI_Datatype newtype;
MPI_Type_contiguous(block_count, MPI_INT, &newtype);
MPI_Type_commit(&newtype);

if (rank==0) {
    MPI_Scatterv(array, sendcounts, displs,
                 newtype, recvbuf, sendcounts[rank],
                 newtype, root, MPI_COMM_WORLD);
}
else {
    MPI_Scatterv(NULL, sendcounts, displs,
                 newtype, recvbuf, reccounts[rank],
                 newtype, root, MPI_COMM_WORLD);
}

MPI_Type_free (&newtype);

print_array(recvbuf,reccounts[rank]);

free(array);array = NULL;
free(sendcounts);sendcounts = NULL;
free(displs);displs = NULL;
free(recvbuf);recvbuf = NULL;
MPI_Finalize();
return 0;
}

推荐答案

有一种方法,但是有点令人费解.

There is a way, but it is a bit convoluted.

这个想法是您创建一个派生的数据类型,该数据类型的两个元素的偏移量为08,然后调整此数据类型的大小,以便上限为一个元素的大小. 然后,可以使用counts={3,3,2}displs={0,3,6}一次MPI_Scatterv(). 请注意,您还需要在接收端创建一个派生的数据类型,否则,当我猜您希望{3, 4, 5, 11, 12, 13}

The idea is you create a derived datatype with two elements at offset 0 and 8, and then resize this datatype so the upper bound is the size of one element. Then you can MPI_Scatterv() once with counts={3,3,2} and displs={0,3,6}. Note you also need to create a derived datatype on the receive side, otherwise MPI task 1 would receive {3, 11, 4, 12, 5, 13} when i guess you expect {3, 4, 5, 11, 12, 13}

这篇关于使用ScatterV将数组拆分为多个进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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