You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenMP并行区调用dynamics函数比临界区慢的原因排查

关于OpenMP并行调用dynamics函数的线程安全与耗时问题

背景与代码说明

我有一个函数void dynamics(A a, std::vector<double> &, std::vector<double> &, std::vector<double>),通过OpenMP创建的线程调用,所有输入都是并行块内创建的线程私有变量。

基础代码如下:

#include <iostream>
#include <vector>
#include <chrono>
using namespace std;

class A {
    // 内部实现代码
};

int main(void)
{
    vector<double> a (12,0.0);
    vector<double> b (12,0.0);

    #pragma omp parallel for shared(a,b)
    for(int id = 0; id < 6; id++) {

        vector<double> a_private (2,0.0);
        vector<double> b_private (2,0.0);
        vector<double> c_private (2,(double)id);
        A d;

        // 记录线程开始时间(chrono实现)
        dynamics(d,a_private,b_private,c_private);
        // 记录线程结束时间并计算耗时

        #pragma omp critical
        {
            for(int i = 0; i < 2; i++) a[i+(2*id)] = a_private[i];
            for(int i = 0; i < 2; i++) b[i+(2*id)] = b_private[i];
        }

    }

    print(a);
    print(b);

    return 0;
}

为避免竞态条件,我将a_private、b_private赋值给全局a、b的操作放在了临界区中。但发现并行执行dynamics时,各线程的单任务耗时比把dynamics放在临界区中串行执行的耗时更长。

临界区执行dynamics的代码片段:

#pragma omp critical
{
    // 记录线程开始时间(chrono实现)
    dynamics(d,a_private,b_private,c_private);
    // 记录线程结束时间并计算耗时
    for(int i = 0; i < 2; i++) a[i+(2*id)] = a_private[i];
    for(int i = 0; i < 2; i++) b[i+(2*id)] = b_private[i];
}

两种执行方式下,a和b的输出完全一致,多次运行结果也相同。

线程安全相关疑问

  • 我认为dynamics是线程安全的,但不确定是否真的安全?
  • 所有输入都是并行块内创建的变量,这些变量是否确实是线程私有?

耗时差异相关疑问

  • 为何并行执行dynamics时,各线程的单任务耗时比临界区中串行执行的耗时更长?我排除了线程创建管理开销的可能,因为两种情况都会创建线程。虽然并行总时间比串行短(有加速比),但单线程耗时差异极大。
  • 会不会即使输入输出是线程私有,dynamics内部仍存在竞态条件?
  • 我没有使用omp_get_num_threads和omp_get_thread_num,这会不会是问题所在?

耗时数据对比

并行区执行dynamics时

ID = 3, Dynamics Time = 410233
ID = 2, Dynamics Time = 447835
ID = 5, Dynamics Time = 532967
ID = 1, Dynamics Time = 545017
ID = 4, Dynamics Time = 576783
ID = 0, Dynamics Time = 624855

临界区执行dynamics时

ID = 0, Dynamics Time = 331579
ID = 2, Dynamics Time = 303294
ID = 5, Dynamics Time = 307622
ID = 1, Dynamics Time = 340489
ID = 3, Dynamics Time = 303066
ID = 4, Dynamics Time = 293090

注:无法提供dynamics的最小复现代码,因为它是教授的专有代码。


内容的提问来源于stack exchange,提问作者Siddhant Kadwe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:05:43