openmp 原子更新与临界区

问题描述 投票:0回答:1

顺序循环、临界区、原子更新。

我有一个由顶点和边组成的二维图。

对于每个顶点,我想计算自由度 (dof) 的数量。 顶点 dof = 连接到该顶点的边数。

我所做的是:

std::vector<size_t> dofs(graph.getNumVertices(), 0);
#pragma omp parallel for
    for (int edgeInd = 0; edgeInd < graph.getNumEdges(); ++edgeInd)
    {
#pragma omp atomic
        ++dofs[graph.getEdge(edgeInd).v1.index];

#pragma omp atomic
        ++dofs[graph.getEdge(edgeInd).v2.index];
    }

效果符合预期。

我的问题:

所有边都分布在不同的线程中。假设只有两个线程:1 和 2。

边缘可以有:

  • 线程 1“独占”的顶点 - 只有线程 1 可以访问
  • 线程 2“独占”的顶点 - 只有线程 2 可以访问
  • 线程 1 和线程 2 之间“共享”的顶点 - 线程 1 和线程 2 都可以访问

问题1:原子更新是否仅在需要时“自行激活”?关键部分(如果应用的话)是否始终处于活动状态?

意思是,下表正确吗(?):

一条边可以有:ATOMIC CRITICAL

  • 线程 1“独占”的顶点 OFF ON
  • 线程 2“独占”的顶点 OFF ON
  • 线程 1 和线程 2 之间“共享”的顶点 ON ON

问题2:

理论上,我期望:

  1. 原子更新 ||循环 - 最快,
  2. 顺序循环 - 比 1) 慢,
  3. 临界区||循环 - 最慢,比 2) 慢。

正确吗?

openmp atomic critical-section
1个回答
0
投票

正如 @PierU 的评论所观察到的,你的原子指令使代码正确,但可能有效地串行。您需要不同的方法。

请参阅我之前对非常类似问题的回答:

https://stackoverflow.com/a/77273690/2044454

https://stackoverflow.com/a/76854330/2044454

用 C++ 编写代码要容易得多,但您可以用 C 来模拟它。

© www.soinside.com 2019 - 2024. All rights reserved.