2013-04-12 42 views
0

我试图两个阵列(每个长度为n的)组合成上根处理接收缓冲器缓冲器地址(秩= 0),以形成长度为2 * n个,即一个单一的阵列的阵列包含所有的值。MPI减少到特定接收

为了简便起见,我的代码如下所示:

#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被初始化为正确的大小,其值为0之前的值减少
  • 的所有进程都偏移数组
  • 之所以使用MPI_Reduce在当时如果RBUF中被设置为0,然后用MPI_SUM减少将使所需的答案

我抬起头文件,一些教程/在线指南,当然,我仍然无法弄清楚我做错了什么。

一个答案,我专门找:

  1. 使用MPI_Reduce这是技术上是可行的?
  2. 我的MPI_Reduce调用是否正确? (指针算术错误?)
  3. 使用MPI是可行/正确的做法还是更好的方法?

感谢

+0

我想我应该尝试使用MPI_Gather,可能会简化/修复问题 – xlm

回答

2

收集(和散射)的一些细节在this answer描述。

ReduceGather是相关但不同的操作。当你呼吁这些载体

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

减少确实做到了正确的事情MPI_Reduce;它花了各种sBufs并添加它们(因为你告诉它执行操作MPI_SUM上的数据),给出{8,3} == {3,2} + {5,1},并将结果放入根处理器接收缓冲区。 (如果你希望每个人都能有答案后,用MPI_Allreduce()代替。)但是请注意,您的电话,以减少,

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

实际上不是有效的;对于减少,每个人都需要以相同的次数拨打电话。而唯一的rBuf重要的是在根本过程,这在这种情况下是排名0.

收集,另一方面,也收集所有的数据,而不是折叠它的总和,产品,xor等操作,它会连接结果。

+0

我明白了,因为rBuf只在根上很重要,所以偏移量没有实际影响?由于偏移[ROOT] = 0。 – xlm

+0

为了减少,这是正确的。 –

0

所以,我想MPI_Gatherv这似乎已经解决了这一问题,经核实为更大数量和数组的大小。

这里就是我所做的:

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

我也试过MPI_Gather但没有工作(它似乎但真正传递类似的方式偏移到我的电话减少没有实际效果)。

从此,我的关于我的具体问题的理解如下:

  1. 这是不可能的/不是预期的使用情况MPI_Reduce
  2. 的减少通话因而不正确,包括偏移在调用没有任何效果
  3. 正确的做法是使用MPI_Gatherv,因为这是这个库调用专门处理(在接收缓冲器位移)

将是巨大的,如果一个有经验的用户MPI(一个或多个)想在权衡。

感谢