c - MPI 在根进程上收集数组

标签 c mpi

我是 MPI 的新手。我有 4 个进程:进程 1 到 3 填充一个 vector 并将其发送到进程 0,进程 0 将 vector 收集到一个非常长的 vector 中。我有可用的代码(太长而无法发布),但进程 0 的 recv 操作笨拙且非常慢。

抽象地说,代码执行以下操作:

MPI::Init();
int id = MPI::COMM_WORLD.Get_rank();

if(id>0) {
    double* my_array = new double[n*m]; //n,m are int
    Populate(my_array, id);
    MPI::COMM_WORLD.Send(my_array,n*m,MPI::DOUBLE,0,50);
}

if(id==0) {
    double* all_arrays = new double[3*n*m];
    /* Slow Code Starts Here */
    double startcomm = MPI::Wtime();
    for (int i=1; i<=3; i++) {
    MPI::COMM_WORLD.Recv(&all_arrays[(i-1)*m*n],n*m,MPI::DOUBLE,i,50);
    }
    double endcomm = MPI::Wtime();
    //Process 0 has more operations...
}
MPI::Finalize();

事实证明,endcomm - startcomm 占总时间的 50%(0.7 秒,而程序完成时间为 1.5 秒)。

是否有更好的方法从进程 1-3 接收 vector 并将它们存储在进程 0 的 all_arrays 中?

我查看了 MPI::Comm::Gather,但不确定如何使用它。特别是,它是否允许我指定进程 1 的数组是 all_arrays 中的第一个数组,进程 2 的数组是第二个,等等?谢谢。

编辑:我删除了“慢”循环,而是将以下内容放在“if” block 之间:

MPI_Gather(my_array,n*m,MPI_DOUBLE,
    &all_arrays[(id-1)*m*n],n*m,MPI_DOUBLE,0,MPI_COMM_WORLD);

导致同样缓慢的性能。这是否与根进程在尝试下一个接收之前“等待”每个接收完成这一事实有关?还是这不是正确的思考方式?

最佳答案

是的,MPI_Gather 将完全做到这一点。来自 MPI_Gather 的 anl 页面:

int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
               void *recvbuf, int recvcnt, MPI_Datatype recvtype, 
               int root, MPI_Comm comm)

这里,sendbuf 是您在每个进程上的数组 (my_array)。 recvbuf 是接收进程上的长数组(all_arrays),短数组将被收集到。接收过程中的短数组正在被复制到它在长数组中的连续位置,所以你不必担心自己做这件事。来自每个进程的数组将在长数组中连续排列。

编辑:

如果接收进程在收集中没有贡献sendbuf,你可能需要使用MPI_Gatherv。相反(感谢@HristoIliev 指出这一点)。

关于c - MPI 在根进程上收集数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10490579/

相关文章:

c - 如何纠正从客户端读取数据的套接字编程错误?

C - 创建和使用结构数组?错误 : expected identifier or '(' before '[' token

c - float 操作会失去精度并改变符号

pthreads - 正确使用 MPI_THREAD_SERIALIZED 和 pthreads

arrays - Mpi4Py - 发送无副本的 numpy 子数组(非连续内存)

c++ - MPI - 随着进程数量的增加没有加速

编译器错误 : cannot convert char* to char

c - 以成员为数组对结构数组进行排序

c++ - MPI_REDUCE 一个动态计算的数组

c - 如何使用 MPI_Gather 从包括主节点在内的不同处理器收集不同长度的字符串?