我正在编写一个测试某些图算法的工具。该工具必须遍历图形中的所有边缘,并在某些条件下标记任一端的节点。然后它必须通过所有节点,确保它们都被标记。代码应该非常简单,但我遇到了一些并发问题。
这是我的代码:
#pragma omp parallel for reduction(+:seen_edges) default(shared)
for (size_t i = 0; i < n_edges; i++)
{
int64_t v0 = node_left(edges[i]), v1 = node_right(edges[i]);
// Do some work...
// This is where I mark nodes if the other end of the edge corresponds to the parent array
if (v0 != v1)
{
if(parents[v0] == v1)
reached[v0] = true;
if(parents[v1] == v0)
reached[v1] = true;
}
// Do more work...
}
#pragma omp parallel for default(shared)
for (size_t i = 0; i < n_nodes; i++)
{
if (i != source && !reached[i])
error("No traversed edge leading to node", i, &n_errors);
}
到达的数组在任何地方都被初始化为false
。
我可以保证在输入中我使用的所有节点都应该被标记,因此不应该打印错误。但是,有时,某些节点仍未标记。
我认为内存共享应该在OpenMP并行区域之间保持一致,并且除了初始化之外,我从未将reached
中的任何元素设置为false。第一个区域末尾的隐式屏障应该阻止任何线程进入第二个区域,直到检查了所有边缘(并且在此测试输入上标记了所有节点)。
我看到两种可能的选择,但没有进一步的解释:
true
吗?true
,但第二个并行区域中的线程之间的内存不一致。这甚至可以在OpenMP中发生吗?如果有人有任何见解,我将不胜感激。欢呼声。
修改:// Do work
部分不使用reached
数组,并且parents
永远不会在程序中修改。