我为什么要使用缩减而不是原子变量?

maf*_*afu 3 c parallel-processing atomic openmp

假设我们想在OpenMP循环中计算一些东西.比较减少

int counter = 0;
#pragma omp for reduction( + : counter )
for (...) {
    ...
    counter++;
}
Run Code Online (Sandbox Code Playgroud)

与原子增量

int counter = 0;
#pragma omp for
for (...) {
    ...
    #pragma omp atomic
    counter++
}
Run Code Online (Sandbox Code Playgroud)

原子访问立即提供结果,而减少仅在循环结束时假定其正确值.例如,减少不允许这样:

int t = counter;
if (t % 1000 == 0) {
    printf ("%dk iterations\n", t/1000);
}
Run Code Online (Sandbox Code Playgroud)

从而提供较少的功能.

为什么我会使用减少而不是原子访问计数器?

Dav*_*aro 10

简短回答:

性能

答案很长:

因为原子变量带有价格,而且这个价格是同步的.为了确保没有竞争条件,即两个线程在同一时刻修改同一个变量,线程必须同步,这实际上意味着您失去并行性,即线程被序列化.

另一方面,减少是可以使用并行缩减算法并行执行的一般操作.阅读本文这篇文章,了解有关并行缩减算法的更多信息.


附录:了解并行减少的工作原理

想象一下你有4线程的场景,你想减少一个8元素数组A.你可以通过3个步骤做到这一点(检查附加的图像以更好地理解我在说什么):

  • 第0步.带索引的线程i<4负责求和的结果A[i]=A[i]+A[i+4].
  • 第1步.带索引的线程i<2负责求和的结果A[i]=A[i]+A[i+4/2].
  • 第2步.带索引的线程i<4/4负责求和的结果A[i]=A[i]+A[i+4/4]

在此过程结束时,您将获得减少Aie 的第一个元素的结果A[0]

在此输入图像描述

  • 基于OpenMP实现,您对并行缩减如何工作的解释是不现实的.至少不是CPUS.它们只是对每个线程进行一次部分求和/减少,然后它们线性地加起/减少每个部分结果.对于`N >> nthreads`这个工作文件.减少`log(nthreads)`在理论上是好的,但在实践中却没有.您可以向OP展示如何手动减少这一点. (2认同)