https://web.archive.org/web/20170227190422/http://hilbert-space.de/?p=22
在这个过时的网站上,它表明手写 asm 会比内在函数带来更大的改进。我想知道即使在 2012 年,这是否是当前的事实。
那么使用 gnu 交叉编译器对内部函数的编译优化是否有所改进?
https://web.archive.org/web/20170227190422/http://hilbert-space.de/?p=22
在这个过时的网站上,它表明手写 asm 会比内在函数带来更大的改进。我想知道即使在 2012 年,这是否是当前的事实。
那么使用 gnu 交叉编译器对内部函数的编译优化是否有所改进?
我的经验是,内在函数并不值得麻烦。编译器很容易在内部函数之间注入额外的寄存器卸载/加载步骤。让它停止这样做的努力比仅仅用原始的 NEON 编写内容更复杂。我在最近的编译器(包括clang 3.1)中看到了这种东西。
在这个层面上,我发现你真的需要准确控制正在发生的事情。如果你做事的顺序几乎没有错误,你就会有各种各样的摊位。用内在函数做这件事就像戴着焊工手套做手术一样。如果代码对性能至关重要,以至于我根本需要内在函数,那么内在函数还不够好。也许其他人在这里有不同的经历。
为了可移植性,我不得不在几个项目中使用 NEON 内在函数。事实是 GCC 不能从 NEON 内在函数生成好的代码。这不是使用内在函数的弱点,而是 GCC 工具的弱点。Microsoft 的 ARM 编译器从 NEON 内部函数生成了出色的代码,在这种情况下无需使用汇编语言。便携性和实用性将决定您应该使用哪个。如果您可以处理编写汇编语言,则编写 asm。对于我的个人项目,我更喜欢在 ASM 中编写时间关键型代码,这样我就不必担心错误/劣质的编译器会弄乱我的代码。
更新: Apple LLVM 编译器介于 GCC(最差)和 Microsoft(最好)之间。它在指令交错和最佳寄存器使用方面效果不佳,但至少它生成合理的代码(在某些情况下与 GCC 不同)。
更新 2 :用于 ARMv8 的 Apple LLVM 编译器得到了显着改进。它现在可以很好地从 C 和内在函数生成 ARMv8 代码。
所以这个问题已经有四年了,现在仍然出现在搜索结果中......
2016 年情况要好得多。
我从汇编转录为内在函数的许多简单代码现在被编译器优化得比我更好,因为我懒得做管道工作(现在有多少不同的管道?),而编译器只需要我要传的权利--mtune=
。
对于寄存器分配可能变得紧张的复杂代码,GCC 和 Clang 仍然可以比手写代码慢两倍……或三倍(ish)。它主要是关于寄存器溢出,所以你应该从你的代码结构中知道这是否有风险。
但他们有时都会发生令人失望的事故。我会说现在这是值得的风险(尽管我是有偿承担风险的),如果你确实被某些东西击中然后提交一个错误。这样,事情就会不断好转。
到目前为止,您甚至可以获得纯 C 代码的自动矢量化,并且内部函数得到正确处理: https ://godbolt.org/z/AGHupq