并行前缀求和的算法

来源:互联网 发布:多个工厂模式 java 编辑:程序博客网 时间:2024/05/21 21:50

本文参考Calvin Lin和Lawrence Snyder的,《Principles of Parallel Programming》(并行程序设计原则)。

与求和紧密相关的操作是前缀求和,在许多并行程序设计语言中也称为扫描(scan)。与求和操作一样,首先仍有n个值的序列,


但希望计算的是如下的序列,


其中,每个 yi 是输入前 i 个元素的和,即有,

以并行方式求解前缀和不如求累加和那样明显(累加和树形分层求和,时间负责度为 logn),因为它需要顺序求解所有中间值。初看起来,好像前缀求和既没有优势,又不可能找到更好的解,但事实上前缀求和能以并行的方式完成。


通过对成对求和方法的观察,可以发现只要对该方法略加修改就可以计算前缀值。求解的思路是,每个存储有 xi  的叶处理器能够计算值 yi ,只要它知道在它左边所有元素的和,即他的前缀,在成对求和的过程中,我们知道所有子树的和,而如果能保留这些信息,就能确定这些前缀而无需直接对它们求和。为做到这一点,我们从根开始,它的前缀(即在序列元素之前的所有元素和)是0。这也是它的左子树的前缀,而它的左子树的总和则是它的右子树的前缀。归纳地应用这一思路,我们可以得到如下规则:

  • 首先,从下往上,一层层的并行,计算出总和
  • 结束后,假想根从它的父节点(实际不存在)处接收一个 0 。
  • 所有的非叶子节点,从它的父节点处接收一个值,将该值转发给它们的左子节点,并将父节点值与它们的左子节点值(这些值在向上成对求和时已经得到)的和发送给右子节点;这些值也是其子节点的前缀。
  • 叶子节点将来自上面的前缀值与它所保存的输入值相加。


图:前缀和的计算。其中,黄色节点是沿树向上扫描,用成对求和算法计算得到的值;浅绿色节点是前缀,沿树向下扫描,用以下简单规则得到:将来自父节点的值送往左子节点,而将来自左子节点的和(上传而来)与来自父节点的值两者相加,并将结果送往右子节点

沿树向下移动的值是子节点的前缀(参见图,其中向下移动的值是浅绿色方框表示)。
这种计算称为并行前缀计算。它在树中进行一次向上和向下扫描,但扫描中处于每一层上的所有操作可以同时完成。因此,在每个节点上最多只需要进行两次加法,一次向上和一次向下,加上路由的逻辑操作。由上可见,并行前缀求和具有对数的时间复杂性。许多类似的顺序操作在这方面要差于并行前缀方法。
顺序和并行算法的根本差别在于构造并行算法时需要改变计算的次序。