如何使用OpenMP并行更新总和
How to parallelize updating sums with OpenMP
下面的循环遍历图的所有边,确定末端节点是否属于同一组,然后将边权重添加到该组的总边权重中。
// TODO: parallel
FORALL_EDGES_BEGIN((*G)) {
node u = EDGE_SOURCE;
node v = EDGE_DEST;
cluster c = zeta[u];
cluster d = zeta[v];
if (c == d) {
// TODO: critical section
intraEdgeWeight[c] += G->weight(u, v);
} // else ignore edge
} FORALL_EDGES_END();
我想将它与OpenMP并行化。我认为if语句中的代码是一个关键部分,如果线程在其中中断,可能会导致竞争条件和错误的结果(正确吗?)。
如果+=
操作可以原子化地进行,我相信问题已经解决了(对吗?)。然而,我查阅了atomic
指令,其中指出:
不幸的是,原子性设置只能指定为通常可以编译到单个处理器中的表达式操作码,例如递增、递减、异或等等。对于例如,它不能包括函数调用、数组索引、重载运算符、非POD类型或多个语句。
我应该使用什么来正确地并行化这个循环?
实际上,atomic update
的可接受语法是:
x++;
x--;
++x;
--x;
xbinop=expr;
x=xbinopexpr;
其中x是标量l-value表达式,expr为任何表达式,包括函数调用,唯一的限制是它必须是标量类型。编译器会注意将中间结果存储在一个临时变量中。
有时最好查阅标准文档,而不是在互联网上阅读教程。遵守OpenMP 3.1标准扩展示例A.22.1c:
float work1(int i)
{
return 1.0 * i;
}
...
#pragma omp atomic update
x[index[i]] += work1(i);
我还认为,如果块是关键部分,则不应该在不序列化写入的情况下从多个线程写入向量。您可以使用#pragma omp critical
将if块中+=的执行限制为一次只能执行一个线程。
您可以将表达式拆分为两部分:将结果赋值为临时值的函数调用,以及将该临时值添加到累加器。在这种情况下,第二个表达式将足够简单,可以使用omp atomic
,假设加法本身不是自定义类型的复杂重载运算符。当然,只有在G->weight(u,v)
是线程安全调用的情况下才能这样做,否则必须使用omp critical
或互斥锁。
- 从C++本机插件更新Vector3数组
- QGraphicsPolygonItem在拖动时未更新QPolygonF坐标
- C++17中的并行执行策略
- cmake更新缓存的变量
- 并行用于C++17中数组索引范围内的循环
- 更新到莫哈韦后出现cmath错误
- 如何在Elixir中调用递归函数并行
- OpenMP:并行更新数组总是需要减少数组吗
- 为什么我的变量没有更新,我的 LED 没有亮起?
- 指针没有更新它在void函数内部指向的值
- 如何使用OpenMP并行这两个循环
- 如何在c++中获取要更新的值
- 已修改的LinkedList未在文本文件本身中更新
- 如何使用OpenMP并行化此矩阵时间矢量运算
- Qt:当QListView获得新条目时,如何更新QStringList
- 如何使用OpenMP使这个循环并行
- 对一个具有重复元素的数组进行排序时更新并行数组
- 如何使用OpenMP并行更新总和
- 并行执行不更新我的变量
- 使用OpenMP原子并行更新矩阵列