【问题标题】:How can I achieve reduction using OpenMP Tasks?如何使用 OpenMP 任务实现减少?
【发布时间】:2018-11-27 16:00:47
【问题描述】:

我有这个执行简单归约的 OpenMP 代码:

for(k = 0; k < m; k++) 
{
      #pragma omp parallel for private(i) reduction(+:mysum) schedule(static) 
      for (i = 0; i < m; i++)
      {
           mysum += a[i][k] * a[i][k];
      }
}

我想创建一个与此代码等效的代码,但使用的是 OpenMP 任务。这是我通过关注this 文章所尝试的:

for(k = 0; k < m; k++) 
{
    #pragma omp parallel reduction(+:mysum)
    {
         #pragma omp single 
         {
                  for (i = 0; i < m; i++) 
                  {
                        #pragma omp task private(i) shared(k)
                        {
                                partialSum += a[i][k] * a[i][k];
                        }
                   }
         }

         #pragma omp taskwait
         mysum += partialSum;
     }
 }

变量partialSum被声明为threadprivate,它也是一个全局变量:

int partialSum = 0;
#pragma omp threadprivate(partialSum)

a 是一个简单的整数数组 (m x m)。

问题是当我多次运行上面的代码(带有任务的代码)时,我得到了不同的结果。

你知道我应该改变什么来完成这项工作吗?

非常感谢

【问题讨论】:

  • 在您的第二个代码中,partialSum 在您的所有线程之间共享。减少处理制作mysum 的私有副本并在最后将它们组合起来,但相同的处理方法没有扩展到partialSum,因此这是数据竞争的主题。您链接的幻灯片使用threadprivate() 指令来解决该问题。我不确定这对你来说是否足够,但它至少可以解决数据竞争。
  • 我不认为partialSum在所有线程之间共享,因为我也将它声明为threadPrivate,就像那篇文章中一样
  • 我想我在问题的最后忽略了这一点。请提供一个minimal reproducible example 展示问题。这不仅会减少此类误解的可能性,而且额外的背景可能证明很重要。
  • 什么误会?我从一开始就陈述了partialSumthreadPrivate 的事实。我认为您应该从头开始阅读整个问题。

标签: c parallel-processing openmp reduction


【解决方案1】:

private 变量未初始化(至少未由它们的外部值初始化)。 i 应该是 firstprivate

如果你只是去掉private(i) shared(k),默认情况下一切都是正确的。 k 来自parallel 部分之外,因此在parallel 部分中隐含shared。这也使得它在任务生成结构中隐含地shared。现在i 也是共享/共享的。如果您改为在本地定义它 (for (int i...),它会隐式地变为 privateparallel 部分,因此在任务生成构造中隐式地变为 firstprivate

你也应该添加

#pragma omp atomic
mysum += partialSum;

另一方面,您不一定需要taskwait(请参阅this answer

请注意,谈话正确地使用了firstprivate

【讨论】:

  • 您在任务生成结构中说kshared,但随后您说它是firstprivate。我有点不清楚k 发生了什么@
  • 抱歉有一个错字并且我误读了你关于i的代码。第一句话(隐含shared/shared 适用于k)。您应该在本地定义i,然后它会隐式变为private/firstprivate,这就是您想要的。您也可以手动指定数据共享属性(只需使用firstprivate(i)
  • 明白。非常感谢您的回答!
  • @CosminIoniță 请注意,最近发布的 OpenMP 5.0 原生支持 task_reduction,但它有点不同,我还没有经验。 AFAIK 它仅在 Intel 18.0 编译器中受支持。
  • 很高兴知道!谢谢,@Zulan!
猜你喜欢
  • 2019-04-27
  • 1970-01-01
  • 2015-06-15
  • 2017-03-22
  • 1970-01-01
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多