在总和上创建优化的归约
Posted
技术标签:
【中文标题】在总和上创建优化的归约【英文标题】:Creating an optimized reduce on sum 【发布时间】:2018-09-03 12:56:25 【问题描述】:我刚刚开始学习 HPC 课程,并且正在做一项任务,我们希望在 MPI_SUM 上实现与 MPI_Reduce 等效的 Reduce 函数......够简单吧?这是我所做的:
我从将数据/数组从所有节点发送到根节点(排名第 0 的过程)的基本概念开始,然后计算总和。
作为第二步,我进一步优化了它,以便每个进程将数据发送到计算总和的镜像,并且这个过程不断重复,直到结果最终出现在根节点(第 0 个进程)中。我的实现如下:
for(k=(size-1); k>0; k/=2)
if(rank<=k)
if(rank<=(k/2))
//receiving the buffers from different processes and computing them
MPI_Recv(rec_buffer, count, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
for(i=0; i<count; i++)
res[i] += rec_buffer[i];
else
MPI_Send(res, count, MPI_INT, k-rank, 0, MPI_COMM_WORLD);
但问题是,与 MPI_Reduce 函数本身相比,这段代码的性能要差得多。
那么我该如何进一步优化呢?如果更好,我可以做些什么不同的事情?我不能使 sum 循环多线程,因为我们需要在单个线程中执行它。我可以优化求和循环,但不确定如何以及从哪里开始。
对于一个非常基本的问题,我深表歉意,但我真的开始涉足 HPC 领域。谢谢!
【问题讨论】:
您说您将数组发送到根节点并在那里计算总和。为什么不在每个进程中建立总和,只向根发送一个整数? @maraca 我需要一个由多个数组的总和组成的数组。例如,如果“a”是每个进程中的一个数组,我想要的结果是 result = a(from process 0) + a(from process 1) + a (from process 2) ... 等等...结果最终将是一个数组。 这里是 Open MPI github.com/open-mpi/ompi/blob/master/ompi/mca/coll/base/…使用的各种算法 一个微优化可以改为使用if(rank <= k/2) MPI_Recv ... else if (rank <= k) MPI_Send...
。可能会稍微改善分支情况。
【参考方案1】:
您的第二种方法是正确的,因为您进行了相同数量的通信,但您已经并行化了 reduce 操作(在您的情况下为 sum)和通信(因为您在子集之间进行通信)。您通常会像 Reduction operator 中描述的那样执行 reduce 操作。
但是,您可能想尝试使用 MPI_Isend 和 MPI_Irecv 进行异步通信以提高性能并更接近 MPI_Reduce 性能。
@GillesGouillardet 提供了一个实现,你可以看到代码中的通信是用 isend 和 irecv 完成的(查找“MCA_PML_CALL(isend”和“MCA_PML_CALL(irecv”)
【讨论】:
以上是关于在总和上创建优化的归约的主要内容,如果未能解决你的问题,请参考以下文章