【问题标题】:Why is OpenMP slower than sequential execution?为什么 OpenMP 比顺序执行慢?
【发布时间】:2020-08-28 04:47:23
【问题描述】:

我有以下代码:

    omp_set_num_threads(10);
    
    int N = 10000;
    int chunk = 1000;
    int i;
    float a[N];

    for (i=0; i < N; i++) 
    {
            a[i] = i;
    }

    #pragma omp parallel private(i)
    {
            #pragma omp for schedule(dynamic,chunk) nowait
            for (i=0; i < N; i++) a[i] = a[i] + a[i];
    } 

顺序代码相同,没有两个 pragma 指令。

连续 ~150us 平行 ~1100us

这是一个巨大的差距,我预计会反过来。

是否有人知道出了什么问题,或者 OpenMP 在后台有很多事情要做? 有人有一个例子,我可以看到并行化的 for 循环更快吗?

谢谢

【问题讨论】:

  • 当做一件事的成本不超过跨多个执行引擎调度事物和协调所有事情的成本时,并行执行通常是最好的。将 10,000 件商品翻倍的成本非常低。
  • 谢谢,这就是问题所在!有没有办法预先分配线程?
  • @gab:线程必须实际启动。它们不会自行产生,也无法通过“预分配”让它们免费存在。 OpenMP 向您隐藏了这样做的复杂性,但仍然需要完成这项工作。
  • 由于所有健全的 OpenMP 运行时都保留一个线程池,因此无论您有多少并行区域,创建线程的成本都只需支付一次。因此,衡量您在许多地方使用 OpenMP 的真实代码中看到的成本的更好方法是,在您对感兴趣的并行区域计时之前,有一个不定时的、空的、并行区域来启动线程。(并且注意你使用的时钟。omp_get_wtime() 是可以的;CPU 消耗不是!)

标签: c++ parallel-processing openmp


【解决方案1】:

启动 10 个线程并管理它们比添加 10,000 个元素更昂贵。如果您在一个真正内核少于 10 个的系统上,它们将竞争时间片,并导致上下文切换和(可能)更多的缓存未命中。而且您选择了动态调度,这意味着需要一些同步来帮助线程确定它们将要执行哪些块(不是很多,但在分配的工作相比之下相当微不足道时足以减慢速度) .

在一个轶事launching a no-op thread and immediately detaching it cost about 10 μs 中,那些线程不需要做任何事情。在您的情况下,这只是启动线程的 100 μs,忽略线程可能引入的所有其他低效问题。

并行化有助于处理大型工作负载,或者当工作人员多次用于许多中等规模的任务时(因此启动线程的成本只是它们所做工作的一小部分)。但是执行 10,000 次加法对 CPU 来说是小菜一碟。您只是做得还不够,无法从并行化中受益。

【讨论】:

    猜你喜欢
    • 2012-05-24
    • 2021-06-18
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    相关资源
    最近更新 更多