OpenMP原子更新与临界区的生效时机及性能对比疑问
OpenMP原子操作与临界区在图顶点自由度计算中的对比分析
场景说明
在计算2D图顶点自由度(顶点自由度为连接该顶点的边数)的场景中,当前基于OpenMP的并行实现代码如下,运行符合预期:
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:原子更新与临界区的生效情况判断
你给出的表格完全正确,具体解释如下:
- 原子更新(
#pragma omp atomic):原子操作仅在多个线程竞争同一内存地址时,才会触发硬件级别的互斥保证。对于线程独占的顶点,只有单个线程访问对应dofs元素,此时原子操作退化为普通自增,无需互斥生效(即表格中的OFF);仅共享顶点会触发原子互斥逻辑(表格中的ON)。 - 临界区(
#pragma omp critical):临界区强制所有线程串行执行区块内代码,无论当前资源是否存在竞争。不管是独占还是共享顶点,只要执行到临界区代码,都会触发锁的获取与释放,因此始终处于生效状态(表格中的ON)。
问题2:性能排序的正确性判断
这个理论性能排序是正确的,原因如下:
- 原子更新+并行循环:仅在共享顶点的自增操作上产生少量原子指令开销,独占顶点的操作可完全并行执行,能充分利用多线程计算能力,是三者中最快的。
- 串行循环:所有操作单线程执行,无并行加速,速度慢于原子更新的并行实现。
- 临界区+并行循环:所有自增操作都需进入临界区,相当于把并行循环强行串行化,还额外增加了锁的获取、释放开销,因此比纯串行循环更慢,是三者中最慢的。
内容的提问来源于stack exchange,提问作者Base0
相关产品推荐
相关产品推荐

