【问题标题】:OpenMP overheadOpenMP 开销
【发布时间】:2011-11-10 04:58:45
【问题描述】:

我使用 OpenMP 和 Intel TBB 并行化了图像卷积和 lu 分解。我正在1-8个核心上测试它。但是,当我在 OPenMP 和 TBB 的 1 个核心上尝试使用 set_num_threads(1) 和 task_scheduler_init InitTBB(1) 分别指定一个线程时;由于 TBB 开销,与顺序代码相比,TBB 性能显示出一些小的下降,但令人惊讶的是,OpenMP 在单核上没有显示任何开销,并且性能与顺序代码完全相同(使用 Intel O3 优化级别)。我正在使用 OpenMP 循环的静态调度。这是现实的还是我做错了什么?

【问题讨论】:

  • 如果num_threadsset_num_threads(num_threads) 的参数仅在运行时(即来自用户输入)已知,是否也会发生这种情况?

标签: openmp tbb


【解决方案1】:

如果您只使用一个线程运行 OpenMP 运行时,它可能不会创建任何线程。

此外,仅使用 OpenMP 并行化指令有时也会使串行代码运行得更快,因为您实际上是在为编译器提供更多信息。例如,工作共享结构告诉编译器循环的迭代是相互独立的,它可能无法自行推断,并且允许编译器使用更积极的优化策略。当然,并非总是如此,但我已经看到它发生在“真实世界的代码”中。

【讨论】:

  • “OpenMP 并行化指令有时也会使串行代码运行得更快,因为您实际上是在为编译器提供更多信息”——这很有趣。不幸的是,当我将 1 个线程与 openmp pragma 一起使用时,我发现性能略有下降,并且自从使用 #ifdefs 来防止它存在时,如果只有 1 个线程。你观察到这个 w.r.t 特定的编译器/代码组合了吗?
  • 哇,我也没听说过。必须尝试一下。有趣!
【解决方案2】:

OpenMP 是编译器完成所有工作的地方。如果编译器知道它将始终是串行代码,它可以完全合法地跳过所有并行位。

据我了解,TBB 基本上只是一个库。它总是必须用必要的部分来装饰你的算法,以并行和串行运行它。

【讨论】:

  • 那么你的意思是说,如果我在 OpenMP 中设置单线程,它的实现就足够智能,可以跳过 OpenMP pragma 并串行运行?
  • 如果你在编译时设置它,从你的问题来看,我认为你有,那么是的,这是可能的。
  • set_num_threads(1) 是 OpenMP 库的一部分,不是 OpenMP 编译器指令,因此编译器不会跳过它。
  • @DirkMausF 当然,但如果实现选择以这种方式或什至以其他方式“魔术”,它可能会内联在头文件中。因此,如果编译器可以证明它没有效果,它可以被内联和优化掉。编译器还可以选择在同一输出中生成两种“风格”的代码,一种是并行的,一种是串行的,如果它愿意的话,并在运行时用一个(相当便宜的)分支选择其中一种。 OpenMP 提供的选项比某些只有预编译代码的库要多得多。
  • 编译器为什么要这样做?检查是否只配置了一个线程然后以非并行方式执行它就足够了……一个如果……那么,与重写整个编译器相比,这没有开销……;)
【解决方案3】:

OpenMP 将代码的修饰部分(#pragma omg for/parallel)分叉到主线程(也可以在没有 OpenMP 的情况下执行)和其他线程中。

如果您配置为仅使用 1 个线程,则这只是主线程,在没有 OpenMP 指令的情况下执行。没有开销,因为执行路径没有分叉。

【讨论】:

    【解决方案4】:

    关于 OpenMP 的事情是编译器为您完成工作,它需要对顺序代码进行最少的修改,并且如果分配给每个线程的任务非常大,通常会产生一些不错的结果。我建议尝试在 c++11 上使用 Pthread 或线程测试您的代码并查看结果。

    【讨论】:

      猜你喜欢
      • 2013-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多