用于超线程的最佳gcc优化开关

时间:2014-04-09 09:37:49

标签: c performance gcc x86-64 hyperthreading

背景

我有一个EP(Embarassingly Parallell)C应用程序在我的笔记本电脑上运行四个线程,其中包含运行在2.67GHz的intel i5 M 480。这个CPU有两个超线程内核。

四个线程在不同的数据子集上执行相同的代码。代码和数据在几个缓存行中都没有问题(完全适合L1,有余地)。代码不包含任何分区,基本上是CPU绑定的,使用所有可用的寄存器并进行一些内存访问(在L1之外)以在序列完成时写入结果。

编译器是mingw64 4.8.1我是最新的。最佳基本优化级别似乎是-O1,这导致四个线程比两个完成得更快。 -O2和更高的运行速度更慢(两个线程比四个完成得更快但比-O1慢)和-Os一样。每个线程平均每秒执行337万个序列,每个序列大约有780个时钟周期。平均每个序列执行25.5个子操作或每30.6个循环一个。

那么两个超线程在30.6个周期中并行执行,一个线程将以35-40或17.5-20个周期顺序执行。

我在哪里

我认为我需要的是生成的代码,它不是那么密集/高效,以至于两个超线程不断地碰撞本地CPU的资源。

这些开关工作得相当好(按模块编译时)

-O1 -m64 -mthreads -g -Wall -c -fschedule-insns

在编译一个#includes所有其他模块的模块时也是如此

-O1 -m64 -mthreads -fschedule-insns -march=native -g -Wall -c -fwhole-program

两者之间没有明显的性能差异。

问题

有没有人对此进行过实验并取得了良好的效果?

4 个答案:

答案 0 :(得分:1)

你说"我认为我需要的是生成的代码,它不是那么密集/高效,以至于两个超线程不断地碰到本地CPU的资源。"。那是相当误导的。

您的CPU拥有一定数量的资源。代码将能够使用一些资源,但通常不是全部。超线程意味着您有两个能够使用资源的线程,因此将使用更高百分比的这些资源。

您想要的是最大化所使用资源的百分比。高效的代码首先会更有效地使用这些资源,添加超线程只会有所帮助。你不会通过超线程获得那么多的加速,但那是因为你已经在单线程代码中获得了加速,因为它更有效率。如果你想要吹牛的权利,超线程给你一个大的加速,当然,从低效的代码开始。如果您想要最高速度,请从高效代码开始。

现在,如果您的代码受到延迟的限制,则意味着它可以执行相当多的无用指令而不会受到惩罚。使用超线程,这些无用的指令实际上是成本。因此,对于超线程,您希望最小化指令的数量,特别是那些被延迟隐藏并且在单线程代码中没有可见成本的指令。

答案 1 :(得分:1)

您可以尝试使用处理器关联性将每个线程锁定到核心。我听说这可以通过一些代码提高15%-50%的效率。节省的是,当处理器上下文切换发生时,缓存中的更改较少等。 这将在仅运行您的应用程序的计算机上更好地工作。

答案 2 :(得分:0)

超线程可能会适得其反。 它发生在计算密集的负载上通常会适得其反。

我会尝试:

  • 在bios级别禁用它并运行两个线程
  • 尝试优化和使用矢量SSE / AVX扩展,最终甚至手动

解释:HT很有用,因为硬件线程可以更有效地调度软件线程。然而,两者都有开销。调度2个线程比调度4更轻量级,如果你的代码已经“密集”,我会尝试执行“更密集”的执行,尽可能地优化2个管道上的执行。

很明显,如果你减少优化,它会更好地扩展,但难度会更快。因此,如果您正在寻找更多可扩展性 - 这个答案不适合您...但如果您正在寻找更快的速度 - 请尝试一下。

正如其他人已经说过的那样,优化时没有一般的解决方案,否则这个解决方案应该已经嵌入到编译器中。

答案 3 :(得分:0)

您可以下载OpenCL或CUDA工具包并为您的图形卡实现一个版本...您可以轻松地将其加速100倍。