【发布时间】:2024-01-05 14:11:01
【问题描述】:
我在使用 Google Benchmark 优化函数时搞砸了,遇到了我的代码在某些情况下意外变慢的情况。我开始尝试它,查看已编译的程序集,并最终提出了一个显示该问题的最小测试用例。这是我想出的展示这种减速的程序集:
.text
test:
#xorps %xmm0, %xmm0
cvtsi2ss %edi, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
addss %xmm0, %xmm0
retq
.global test
此函数遵循函数声明 extern "C" float test(int); 的 GCC/Clang 的 x86-64 调用约定注意注释掉的 xorps 指令。取消注释这条指令可以显着提高函数的性能。使用我的机器和 i7-8700K 对其进行测试,Google 基准测试显示函数 没有 xorps 指令需要 8.54ns (CPU),而函数 with @987654325 @ 指令耗时 1.48ns。我已经在具有不同操作系统、处理器、处理器代和不同处理器制造商(英特尔和 AMD)的多台计算机上对此进行了测试,它们都表现出相似的性能差异。重复 addss 指令会使减速更加明显(在一定程度上),并且使用此处的其他指令(例如 mulss)甚至混合指令仍然会发生这种减速,只要它们都依赖于 @ 中的值987654328@ 在某种程度上。值得指出的是,只有调用xorpseach 函数调用才能带来性能提升。使用循环外的xorps 调用循环(如Google Benchmark 所做的那样)对性能进行采样仍然显示性能较慢。
由于这是一种专门添加指令可以提高性能的情况,这似乎是由 CPU 中的一些非常低级的东西引起的。由于它发生在各种各样的 CPU 上,这似乎是故意的。但是,我找不到任何文档来解释为什么会发生这种情况。有人对这里发生的事情有解释吗?这个问题似乎取决于复杂的因素,因为我在原始代码中看到的减速只发生在特定的优化级别(-O2,有时是-O1,但不是-Os),没有内联,并且使用特定的编译器(Clang , 但不是 GCC)。
【问题讨论】:
标签: clang x86-64 cpu-architecture sse microbenchmark