您已经问过如何加快对单个函数的单个调用的评估。除非评估时间以小时为单位,否则不清楚为什么值得费心加快速度。如果您坚持要加快函数执行本身,则必须检查其内容以查看其某些方面是否可并行化。您没有提供任何关于它计算什么或如何计算的信息,因此很难就这方面提供任何进一步的建议。 hardmath 的回答提出了一些您可以使用的想法,具体取决于您的函数的实际内部结构。
但是,通常问您问题的人实际上会针对 x,y,z 的不同值(例如 x1,y1,... x2,y2,... xN)多次调用该函数(例如 N 次) ,yN, ... 使用你的词汇)。
是的,如果您加快函数的执行速度,那么进行集体调用将会加快速度,而这正是人们想要的。如果是这种情况,加速整体执行“在技术上很容易”:对函数进行 N 次并行调用。然后所有逐点评估同时发生。为了完成这项工作,您几乎已经从要处理的值中创建了向量(因此这种技巧称为“数据并行”编程)。所以你真正想要的是:
PARALLEL DO I=1,N
RESULT(I)=F(X[J],Y[J], ...)
END PARALLEL DO
如何实现 PARALLEL DO 取决于您拥有的编程语言和库。
这通常只在 N 是一个相当大的数字时才有效,但 f 执行的成本越高,有效的 N 就越小。
您还可以利用函数的结构来提高效率。如果 f 以与常用案例相同的方式计算某些内部值,您可能能够
打破特殊情况,预先计算,然后使用这些结果计算每个单独调用的“其余 f”。
如果您正在组合(“减少”)所有函数的结果(例如,对所有结果求和),您可以在 PARALLELL 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