【问题标题】:Why is my OpenMP implementation slower than a single threaded implementation?为什么我的 OpenMP 实现比单线程实现慢?
【发布时间】:2011-02-19 06:20:26
【问题描述】:

我正在学习 OpenMP 并发,并尝试了一些现有的代码。在这段代码中,我试图让所有的 for 循环并行。然而,这似乎使程序比单线程版本慢得多,至少慢 10 倍,甚至更多。

这里是代码:http://pastebin.com/zyLzuWU2

我还使用了 pthreads,结果证明它比单线程版本更快。

现在的问题是,我在我的 OpenMP 实现中做错了什么导致速度变慢?

谢谢!

编辑:单线程版本只是没有所有#pragmas的版本

【问题讨论】:

  • 你是在单核系统上运行它吗?
  • 除非每个内核使用不超过 1 个线程,否则它们可能会相互竞争共享资源。引入并行化并不会自动使程序运行得更快。
  • @matt:也许您可以写一个答案来说明这一点,也许还有一些解决方法的建议?谢谢!
  • 您的代码中有不正确且被忽略的编译指示 - 但您应该了解 OpenMP 概念。我所说的编译指示是“#pragma omp end”。 OpenMP pragma 适用于 C/C++ 中的结构化块,因此不需要 end pragma。只有在 Fortran 中没有块 ({}) 表示您需要使用结束指令。

标签: c openmp


【解决方案1】:

我在您的代码中看到的一个问题是您在非常小的循环(例如 8 或 64 次迭代)中使用 OpenMP。由于开销,这将不是有效的。如果您想使用 OpenMP 解决 n-queens 问题,请查看针对分支定界问题的 OpenMP 3.0 任务和线程并行性。

【讨论】:

  • 任务要求你看看你是如何以不同的方式并行化的。然而,在使用 OpenMP 任务并行化 nqueens 问题时,网络上有几篇论文和演示文稿显示几乎线性加速(2 个线程的速度是串行的两倍,4 个线程的速度几乎是串行的 4 倍,等等)。
【解决方案2】:

我认为您的代码过于复杂,无法在此处查看。我立即看到的一个错误是它甚至都不正确。在您使用omp parallel for 进行求和的地方,您必须使用reduction(+: yourcountervariable) 将不同线程的结果正确组合在一起。否则一个线程可能会覆盖其他线程的结果。

【讨论】:

  • 正确的子句是“reduction(+: yourCounterVariable)”。如果没有这个或使用原子、关键或锁定,您的结果甚至都不正确。
【解决方案3】:

至少有两个原因:

  1. 您只对一个非常简单的循环进行了 8 次迭代。您的运行时将完全由设置所有线程所涉及的开销支配。

  2. 在某些地方,critical 部分会引起争用;所有线程将不断尝试访问临界区,并相互阻塞。

【讨论】:

    猜你喜欢
    • 2016-01-29
    • 1970-01-01
    • 2014-02-09
    • 2021-10-12
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多