MPI减少到特定的接收缓冲区地址

时间:2013-04-12 07:28:03

标签: c parallel-processing mpi

我正在尝试将两个数组(每个长度为n)组合到根进程(rank = 0)上的接收缓冲区中,以形成长度为2 * n的数组,即包含所有值的单个数组。

为简洁起见,我的代码类似于以下内容:

#define ROOT 0

int myFunction(int* rBuf, int n) {
  int* sBuf = malloc(n*sizeof(int));

  // Do work, calculate offset, count etc.

  MPI_Reduce(sBuf, rBuf+offset[rank], counts[rank], 
             MPI_INT, MPI_SUM, ROOT, MPI_COMM_WORLD);
}
// where offset[rank] is amount to offset where it is to be received
// offset[0] = 0, offset[1] = n
// counts contains the length of arrays on each process

然而,当我检查rBuf时,它被缩减为没有偏移的rBuf,例如:

// Rank 0: sBuf = {3, 2}
// Rank 1: sBuf = {5, 1}
// Should be rBuf = {3, 2, 5, 1}    
rBuf = {8, 3, 0, 0}

其他信息:

  • rBuf初始化为正确大小,在reduce
  • 之前的值为0
  • 所有进程都有偏移数组
  • 当时使用MPI_Reduce的原因是,如果rBuf设置为0,那么使用MPI_SUM减少会得到所需的答案

我查了一些文档,一些教程/指南在线,当然这样,我仍然无法弄清楚我做错了什么。

作为答案,我特意寻找:

  1. 这在技术上是否可以使用MPI_Reduce?
  2. 我的MPI_Reduce通话是否正确? (指针算术中的错误?)
  3. 使用MPI是可行/正确的做法还是更好的方法?
  4. 由于

2 个答案:

答案 0 :(得分:2)

this answer中详细描述了聚集(和分散)。

ReduceGather相关但操作不同。当您在这些向量上调用MPI_Reduce

// Rank 0: sBuf = {3, 2}
// Rank 1: sBuf = {5, 1}

Reduce完全做对了;它花了各种sBuf并添加它们(因为你告诉它对数据执行操作MPI_SUM),给出{8,3} == {3,2} + {5,1},并将结果放在根处理器接收缓冲区中。 (如果您希望每个人都获得答案,请改用MPI_Allreduce()。)但请注意您对Reduce的调用,

 MPI_Reduce(sBuf, rBuf+offset[rank], counts[rank], 
             MPI_INT, MPI_SUM, ROOT, MPI_COMM_WORLD);

实际上并不有效;对于Reduce,每个人都需要使用相同的计数进行呼叫。并且唯一重要的rBuf是根进程中的那个,在这种情况下是0级。

另一方面,收集收集所有数据,但不是使用sum,product,xor等操作将其折叠,而是将结果连接起来。

答案 1 :(得分:0)

所以我尝试了MPI_Gatherv,这似乎解决了这个问题,验证了更大数量和数量的数组。

这就是我的所作所为:

MPI_Gatherv(sBuf, counts[rank], MPI_INT, c, counts, offset, MPI_INT, 
            ROOT, MPI_COMM_WORLD);

我也尝试过MPI_Gather,但这不起作用(看起来真的以与我的reduce调用类似的方式传递偏移没有实际效果)。

由此,我对我的具体问题的理解如下:

  1. 这不可能/不是MPI_Reduce的预期用例
  2. reduce调用因此不正确,包括调用中的偏移无效
  3. 正确的方法是使用MPI_Gatherv,因为这是这个库调用专门解决的问题(接收缓冲区中的位移)
  4. 如果有经验的MPI用户想要权衡,那就太棒了。

    由于