Optimization GCC检测的可执行文件如何比未检测的可执行文件更快?

Optimization GCC检测的可执行文件如何比未检测的可执行文件更快?,optimization,gcc,compiler-construction,instrumentation,pgo,Optimization,Gcc,Compiler Construction,Instrumentation,Pgo,我正在根据规范基准测试GCC概要文件引导优化的开销。我在一些基准测试中得到了一些奇怪的结果。事实上,我的两个基准测试在测试时运行得更快 正常的可执行文件是用:-g-O2-march=native编译的 插入指令的可执行文件使用:-g-O2-march=native-fprofile generate-fno vpt编译 我使用的是GCC4.7(确切地说是谷歌的分支)。运行基准测试的计算机具有Intel(R)Xeon(R)CPU E5-2650@2.00GHz bwaves是Fortran基准测试

我正在根据规范基准测试GCC概要文件引导优化的开销。我在一些基准测试中得到了一些奇怪的结果。事实上,我的两个基准测试在测试时运行得更快

正常的可执行文件是用:-g-O2-march=native编译的

插入指令的可执行文件使用:-g-O2-march=native-fprofile generate-fno vpt编译

我使用的是GCC4.7(确切地说是谷歌的分支)。运行基准测试的计算机具有Intel(R)Xeon(R)CPU E5-2650@2.00GHz

bwaves是Fortran基准测试和libquantum

结果如下:

bwaves-normal: 712.14 
bwaves-instrumented: 697.22 
  => ~2% faster 

libquantum-normal: 463.88
libquantum-instrumented: 449.05
  => ~3.2% faster
我多次运行基准测试,认为这可能是ma机器上的一个问题,但每次我都确认了它们

我可以理解某些程序的开销很小,但我看不出有任何改进的理由

所以我的问题是:GCC检测的可执行文件如何比优化的普通可执行文件更快


感谢查看GCC文档,它看起来像是
-fprofile generate
确实激活了一些特定的代码转换,以使分析更容易/更便宜,因此插入指令的代码实际上不是原始的代码+指令。这些更改可以加快代码的速度,添加代码也会改变缓存行为。如果看不到违规代码,就很难知道。从我(很久以前)的愚弄中可以看出,当分析智能化地完成时,只需要很少的代码更改


只是好奇:与上面相比,考虑配置文件编译的代码表现如何?

我可以想到两种可能性,都与缓存有关

一是计数器增量“加热”了一些重要的缓存线。 其次,添加插装所需的结构会导致一些频繁使用的数组或变量落入不同的缓存线


另一个问题是,分析/增加计数器不一定每次都发生在for循环中——如果循环中没有“中断”或“返回”,允许编译器优化循环外的增量。

我不认为这在我们可以构建和实验的小测试用例上是可复制的?不幸的是,没有,我不能共享规范的源代码/可执行文件,因为它是商业性的:(可能是你的性能是由缓存效果决定的。添加代码会改变哪些缓存线会被命中;如果你在没有插装的情况下受到严重干扰,你可以看到这一点。有没有理由相信你的程序会触及大量缓存?我不太清楚,但我知道有些基准非常占用内存。Perhaps就是这种情况。事实上,它可以改变内存效果。关于@IraBaxter建议的缓存效果,代码中有预取指令吗?添加代码通常不会消除缓存问题(缓存大小、内存带宽和延迟不会神奇地改变,但额外的代码可能“免费”运行)但可能确实会给缓存带来更大的压力。然而,预取是另一回事,如果没有足够早地进行预取(或使用错误的访问提示),它实际上可能比不进行预取慢。在这种情况下,“更多的代码”因此,稍微延迟执行确实可以让它运行得更快。对于bwaves,PGO编译速度快3.5%,而对于libquantum,几乎快15%。