[英]parallel programming in OpenMP
我有以下一段代码。
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]];
}
根据这篇文章的讨论,如果offset[i1] == offset[i2]
for i1 != i2
,上面的代码可能会导致错误的cnt
。 我能做些什么来避免这种情况?
这段代码:
#pragma omp parallel for shared(cnt, offset) private(i)
for (i = 0; i < n; ++i) {
++cnt[offset[i]];
}
在数组cnt
更新期间包含竞争条件,要解决它,您需要保证这些更新的互斥。 这可以通过(例如) #pragma omp atomic update来实现,但正如评论中已经指出的那样:
但是,这仅解决了正确性问题,并且由于大量的缓存争用和同步需求(包括错误共享),可能效率非常低。 唯一的解决方案是让每个线程拥有其私有的 cnt 副本,并在最后减少这些副本。
另一种解决方案是每个线程都有一个私有数组,并在并行区域结束时手动将所有这些 arrays 减少为一个。 可以在此处找到此类方法的示例。
幸运的是,使用OpenMP 4.5 ,您可以使用专用 pragma 减少 arrays,即:
#pragma omp parallel for reduction(+:cnt)
您可以查看此示例以了解如何应用该功能。
值得一提的是,关于减少 arrays与@Jérôme Richard所指出的原子方法相比:
请注意,仅当数组不是很大时,这才很快(在这种关于平台的特定情况下,如果值不冲突,基于原子的解决方案可能会更快)。 所以这是 m << n。 –
一如既往,分析是关键;因此。 您应该使用上述方法测试您的代码,以找出最有效的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.