【问题标题】:MPI gather array on root processMPI 在根进程上收集数组
【发布时间】:2012-05-16 11:06:01
【问题描述】:

我是 MPI 的新手。我有 4 个进程:进程 1 到 3 填充一个向量并将其发送到进程 0,进程 0 将向量收集到一个非常长的向量中。我有可以工作的代码(太长无法发布),但是进程 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 的向量并将它们存储在进程 0 的 all_arrays 中?

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

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

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

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

【问题讨论】:

  • 只是一个简短的评论 - C++ 绑定在当前 MPI 标准版本 2.2 中已弃用,并将在即将推出的 MPI 3.0 中完全删除。出于可移植性的原因,建议您学习和使用 C 接口。
  • 你的程序中nm有多大,你的机器之间有什么样的连接?
  • Hristo,谢谢——我将代码更改为 C 接口。
  • suszterpatt-- n=3500,m=7,所以 n*m=24,500。我不知道如何确定连接。如果有帮助,现在我正在我的笔记本电脑 Macbook Pro 2.2 GHz Core i7 上测试此代码,但很快会在 sun Grid Engine 集群上运行它。
  • @covstat 应该没有连接问题,因为您在共享内存上。你期待看到什么样的表现?无论您使用哪种 MPI 操作,这种数据收集总是比最近邻居之间的交换慢。我对 Mac 不熟悉,所以也可能是操作系统/编译器/MPI 构建问题,这超出了我的知识范围。

标签: c mpi


【解决方案1】:

是的,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 指出这一点)。

【讨论】:

  • 由于 0 级不发送给自己,他最好使用MPI_Gatherv()
  • @RestlessC0bra, MPI_Gathev 允许指定来自组中每个等级的数据量,特别是根本没有数据(0)。 MPI_Gather 无法做到这一点,因此我发表了评论。
猜你喜欢
  • 1970-01-01
  • 2014-08-27
  • 2020-08-09
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多