这个问题似乎含糊不清,但让我解释一下。
假设我们有一个函数f(x,y,z ....),我们需要在点(x1,y1,z1 .....)找到它的值。
最简单的方法是将(x,y,z ......)替换为(x1,y1,z1 .....)。
现在假设该函数在评估中花费了大量时间,我想并行化算法来评估它。显然它也取决于功能的性质。
所以我的问题是:在“思考”并行化f(x,y,z ......)时,我必须寻找什么约束?
如果可能,请分享学习链接。
答案 0 :(得分:5)
答案 1 :(得分:1)
您已经问过如何加快对单个函数的单次调用的评估。除非评估时间以小时计算,否则不清楚为什么值得花时间加快速度。如果你坚持加速函数执行本身,你必须检查它的内容,看看它的某些方面是否可以并行化。您尚未提供有关其计算内容或如何执行此操作的任何信息,因此很难就此方面提供任何进一步的建议。 hardmath的回答提出了一些你可以使用的想法,具体取决于你函数的实际内部结构。
然而,通常人们问你的问题实际上是对x,y,z的不同值多次(比如N次)调用函数(例如,x1,y1,... x2,y2,... xN ,yN,...使用你的词汇)。 是的,如果你加快了函数的执行速度,那么集体调用将会加速,这就是人们想要的。如果是这种情况,加速整体执行在“技术上很容易”:N并行调用该函数。然后所有的逐点评估都在同一时间进行。为了使这个工作,你几乎从你想要处理的值中产生向量(所以这种技巧称为“数据并行”编程)。所以你真正想要的是:
PARALLEL DO I=1,N
RESULT(I)=F(X[J],Y[J], ...)
END PARALLEL DO
如何实现PARALLEL DO取决于您拥有的编程语言和库。 这通常只有在N是一个相当大的数字时才有效,但执行的f越贵,有效N越小。
您还可以利用函数的结构来提高效率。如果f为常用情况计算某些内部值的方式相同,则可能 打破特殊情况,预先计算这些情况,然后使用这些结果计算每个单独呼叫的“其余f”。
如果要组合(“减少”)所有函数的结果(例如,对所有结果求和),则可以在外部 PARALELL DO循环中执行此操作。如果你试图在循环中组合结果,那么你将得到“循环携带依赖”并且你将得到错误的答案,或者它将不会以你期望的方式并行,这取决于你的编译器或并行库。如果组合是一些关联/可交换操作(例如“sum”),则可以 有效地组合答案,通过构建等于二叉树的内容并运行 的评估平行。这是一个在数据并行计算中经常出现的不同问题,但我们不会在这里进一步讨论。
并行for循环的开销通常很高(分支线程很昂贵)。所以通常人们会在几次迭代中划分开销:
PARALLEL DO I=1,N,M
DO J=I,I+M
RESULT(J)=F(X[J],Y[J], ...)
END DO
END PARALLEL DO
常数M需要校准效率;你必须“调整”它。你还必须注意N可能不是M的倍数;这需要一个额外的干净循环来处理边缘条件:
PARALLEL DO I=1,int(N/M)*M,M
DO J=I,I+M
RESULT(J)=F(X[J],Y[J], ...)
END DO
END PARALLEL DO
DO J=int(N/M)*M,N,1
RESULT(J)=F(X[J],Y[J], ...)
END DO