我正在尝试将两个数组(每个长度为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初始化为正确的大小(值为0s)
所有过程都有偏移数组
当时使用MPI_Reduce的原因是,如果rBuf设置为0s,则使用MPI_SUM进行减少将给出所需的答案
我查找了文档,在线一些教程/指南,当然还有SO,但我仍然无法弄清楚自己在做什么错。
要寻找答案,我专门在寻找:
使用MPI_Reduce在技术上可行吗?
我的MPI_Reduce呼叫正确吗? (指针算术错误?)
使用MPI是可行/正确的做法还是更好的方法?
谢谢
最佳答案
聚集(和散布)在this answer中进行了详细描述。
Reduce和Gather是相关的,但操作不同。当您在这些引导程序上调用MPI_Reduce
时
// Rank 0: sBuf = {3, 2}
// Rank 1: sBuf = {5, 1}
减少完全是正确的事情;它采用了各种
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。另一方面,Gather也会收集所有数据,但它不会将结果与求和,乘积,异或等运算合并在一起,而是将结果合并在一起。