首页 > 解决方案 > 在不能应用 omp atomic/reduction 的情况下,我们可以使用 omp critical 来提高效率吗?

问题描述

我在 C++ 中面临一个问题。

假设我们有vector<SomeClass> v并且我们想要添加v使用多线程的所有元素。(的大小vN。)我们有一个重载的+=运算符 inSomeClass但这不是原子兼容的。

SomeClass sum; // init by "zero" but not exactly a single (int)
#pragma omp parallel for
for (int i=0; i<N; ++i) {
   #pragma omp critical
   {
      sum += v[i];
   }
}

我的实验表明,这段代码的运行时间与单线程的类似。我认为这是由于critcial一次只允许一个线程评估添加的部分。(我无法利用多线程)。替代方法是使用atomicor ( reduction),但它们不可用,因为+=不适用于原子变量。

在这种情况下,我们能做什么?我应该在这里退出使用多线程吗?非常感谢。

标签: c++openmp

解决方案


你需要做减法。reduction(op:var)如果openMP的标准指令不支持该类,您可以手动添加它。

每个线程将向量值相加到一个私有累加器中。然后,将私有累加器相加成一个全局累加器(对于整个循环,每个线程只需执行一次,而不是在每次迭代时)

SomeClass sum; // init by "zero" but not exactly a single (int)
#pragma omp parallel
{
    SomeClass mySum=0; //local accumulator, init with 0 or whatever the "zero" is for that class
    #pragma omp for
    for (int i=0; i<N; ++i) mySum += v[i];

    #pragma omp critical
    sum += mySum; //The critical section is entered only once
}

推荐阅读