【问题标题】:parallel programming in OpenMPOpenMP 中的并行编程
【发布时间】:2021-07-16 12:55:41
【问题描述】:

我有以下代码。

for (i = 0; i < n; ++i) {
  ++cnt[offset[i]];
}

其中offset 是一个大小为n 的数组,其中包含[0, m) 范围内的值,cnt 是一个大小为m 的数组,初始化为0。我使用OpenMP 对其进行并行化,如下所示。

#pragma omp parallel for shared(cnt, offset) private(i)
for (i = 0; i < n; ++i) {
  ++cnt[offset[i]];
}

根据这个post的讨论,如果offset[i1] == offset[i2]换成i1 != i2,上面这段代码可能会导致cnt不正确。我该怎么做才能避免这种情况?

【问题讨论】:

    标签: c++ c multithreading parallel-processing openmp


    【解决方案1】:

    这段代码:

    #pragma omp parallel for shared(cnt, offset) private(i)
    for (i = 0; i < n; ++i) {
      ++cnt[offset[i]];
    }
    

    在数组cnt 更新期间包含竞争条件,要解决它,您需要保证这些更新的互斥。这可以通过(例如)#pragma omp atomic update 来实现,但正如 cmets 中已经指出的那样:

    但是,这解决了正确性问题,并且可能非常糟糕 由于严重的缓存争用和同步需求,效率低下 (包括虚假分享)。那么唯一的解决方案就是让每个 线程它的私有副本 cnt 并在最后减少这些副本。

    另一种解决方案是拥有一个私有数组 per 线程,并在并行区域结束时手动将所有这些数组归为一个。这种方法的一个例子可以在here找到。

    幸运的是,通过 OpenMP 4.5,您可以使用专用 pragma 减少数组,即:

    #pragma omp parallel for reduction(+:cnt)
    

    您可以查看this example,了解如何应用该功能。

    值得一提的是,关于数组的减少@Jérôme Richard 指出的原子方法:

    请注意,仅当数组不是很大时(基于原子的 在关于平台的这种特定情况下,解决方案可能会更快 如果值不冲突)。所以这是 m

    一如既往地分析是关键!;因此,您应该使用上述方法测试您的代码,以找出最有效的方法。

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 2023-04-11
      • 2011-12-29
      相关资源
      最近更新 更多