有时循环的迭代之间存在真正的依赖性,通过简单地私有化导致依赖性的变量并不能除去该依赖性。例如,查看以下从一次迭代到下一次迭代累计值的代码。
示例 3-11 可以并行化的循环for (i=1; i < 1000; i++) { sum += a[i]*b[i]; /* S1 */ }
在此示例中,循环计算两个数组的向量乘积,并将结果赋给一个称为 sum 的公共变量。该循环不能以简单的方式并行化。编译器可以利用语句 S1 中计算的关联特性,并为每个线程分配一个称为 psum[i] 的私有变量。变量 psum[i] 的每个副本均初始化为 0。每个线程以自己的变量 psum[i] 副本计算自己的部分和。执行循环之前,所有部分和均加到初始变量 sum 上。在本示例中,变量 sum 称为约简变量,因为它计算和约简。然而,将标量变量提升为约简变量存在的危险是:累计舍入值的方式会更改 sum 的最终值。只有在您专门授权这样做时,编译器才执行该变换。