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

用于超线程的最佳gcc优化开关,c,performance,gcc,x86-64,hyperthreading,C,Performance,Gcc,X86 64,Hyperthreading,背景 我的笔记本电脑上有一个运行四个线程的EP(令人尴尬的并行)C应用程序,其中包含一个运行在2.67GHz的intel i5 M 480。这个CPU有两个超线程内核 这四个线程在不同的数据子集上执行相同的代码。代码和数据在装入几个缓存线时没有问题(完全装入一级缓存线,并留有空间)。该代码不包含任何分区,基本上受CPU限制,使用所有可用寄存器,并在序列完成时进行一些内存访问(L1之外)以写入结果 编译器是mingw64 4.8.1,是相当新的。最好的基本优化级别似乎是-O1,这会导致四个线程比两

背景

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

这四个线程在不同的数据子集上执行相同的代码。代码和数据在装入几个缓存线时没有问题(完全装入一级缓存线,并留有空间)。该代码不包含任何分区,基本上受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 -fschedule-insns -march=native -g -Wall -c -fwhole-program
两者之间没有明显的性能差异

问题

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

你说“我想我需要的是生成的代码,它不是那么密集/高效,以至于两个超线程在本地CPU资源上不断冲突。”。那是相当误导的

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

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


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

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

超链接可能会适得其反。 这种情况下,计算密集型负载通常会适得其反

我会尝试:

  • 在bios级别禁用它并运行两个线程
  • 尝试优化和使用vector SSE/AVX扩展,最终甚至手动
说明:HT很有用,因为硬件线程的调度效率比软件线程高。然而,两者都存在开销。调度2个线程比调度4更轻量级,如果您的代码已经“密集”,我会尝试“密集”执行,尽可能优化2个管道上的执行

很明显,如果你优化得更少,它的伸缩性更好,但它会更快。因此,如果您正在寻找更多的可伸缩性-这个答案不适合您。。。但是如果你想要更快的速度,试试看


正如其他人已经指出的,优化时没有通用的解决方案,否则此解决方案应该已经嵌入到编译器中。

您可以下载OpenCL或CUDA工具包,并为图形卡实现一个版本。。。您可能可以轻松地将速度提高100倍。

对此没有单一的答案。正如您自己所注意到的,在您的情况下,较高的优化(
-O2
)比较低的优化(
-O1
)的性能更差。(不要忘记检查,例如,
-O3
)。这在很大程度上取决于您的代码和用例。你只需要进行实验和基准测试。我已经做了很多实验和基准测试:-)我更想知道我是否忽略了任何明显或模糊的东西。你能发布一些代码并展示你是如何分析你的代码的吗?你在使用OpenMP吗?@Z boson:当我在我的另一台笔记本电脑上分析时,我使用了AMD的CodeAnalyst。我的程序运行在Windows7上,在没有包装器/框架的情况下使用线程函数。我说“我需要什么”的意思是生成的代码,以便两个相同的代码序列最终实现某种类型的执行交错,以便在访问CPU资源时,它们的冲突程度较小。超线程是一种机制,当编译器在按顺序执行的管道利用率方面做得不好时,可以优化资源利用率,例如,如果一个线程由于缓存未命中而需要等待(导致管道暂停)。也就是说,在不进行攻击性指令重新排序(试图防止这种情况)的优化级别上,它将是最有效的。如果您的编译器已经很好地避免了管道
-O1 -m64 -mthreads -fschedule-insns -march=native -g -Wall -c -fwhole-program