【问题标题】:Arm Neon Intrinsics vs hand assemblyArm Neon Intrinsics 与手工组装
【发布时间】:2012-04-07 09:15:00
【问题描述】:

https://web.archive.org/web/20170227190422/http://hilbert-space.de/?p=22

在这个已经过时的网站上,它表明手写 asm 会比内在函数带来更大的改进。我想知道这是否是 2012 年现在的现实。

那么使用 gnu 交叉编译器改进了内在函数的编译优化吗?

【问题讨论】:

  • 嘿,我的网站没有过时。我现在只有其他工作要做。 :-)
  • 你的网站很棒。当我试图弄清楚这些东西时,我在那里花了很多时间。

标签: arm neon intrinsics


【解决方案1】:

我的经验是,内在函数并不值得麻烦。编译器很容易在内部函数之间注入额外的寄存器卸载/加载步骤。让它停止这样做的努力比仅仅用原始的 NEON 编写内容更复杂。我在最近的编译器(包括 clang 3.1)中看到了这种东西。

在这个级别上,我发现您确实需要准确控制正在发生的事情。如果你做事的顺序几乎没有错误,你就会有各种各样的摊位。用内在函数做这件事就像戴着焊工手套做手术一样。如果代码对性能至关重要,以至于我根本需要内在函数,那么内在函数还不够好。也许其他人在这里有不同的经历。

【讨论】:

  • 这符合我使用 ARM/Neon 的经验。对于 x86/SSE 和 PowerPC/AltiVec,编译器足够好,用内在函数编写的 SIMD 代码很难用汇编器击败,但 Neon 代码生成(至少使用 gcc)似乎没有那么好,而且如果您准备手动编写汇编程序,则不难将 Neon 内在 SIMD 代码击败 2 倍。
  • 2x 也符合我的经验。我们不是在这里谈论小调整,我什至不擅长它。
  • 同上 - 我注意到你可以在汇编程序中做的很多有助于提高性能的事情不能通过内在函数来表达,所以除非编译器足够聪明来做这些事情(例如地址寄存器更新)然后你运气不好。
  • 一种方法可能是最初在内部函数中编写代码,测量性能,然后为任何仍需要进一步提高速度的例程转到汇编程序。
  • 我完全同意。内在的东西根本不值得努力。如果您非常了解 Neon 的工作原理,您确实可以强制改进内在函数的代码生成,但是,您根本不需要内在函数。
【解决方案2】:

为了可移植性,我不得不在几个项目中使用 NEON 内部函数。事实是 GCC 不能从 NEON 内在函数生成好的代码。这不是使用内在函数的弱点,而是 GCC 工具的弱点。 Microsoft 的 ARM 编译器从 NEON 内部函数生成了出色的代码,在这种情况下无需使用汇编语言。便携性和实用性将决定您应该使用哪个。如果您可以处理编写汇编语言,则编写 asm。对于我的个人项目,我更喜欢在 ASM 中编写时间关键型代码,这样我就不必担心错误/劣质的编译器会弄乱我的代码。

更新:Apple LLVM 编译器介于 GCC(最差)和 Microsoft(最好)之间。它在指令交错和优化寄存器使用方面效果不佳,但至少它生成了合理的代码(在某些情况下不像 GCC)。

更新 2: ARMv8 的 Apple LLVM 编译器得到了显着改进。它现在可以很好地从 C 和内在函数生成 ARMv8 代码。

【讨论】:

  • 有什么理由不给你发现的编译器命名吗? RVDS?还是别的什么?
  • 另一家公司是微软。他们的ARM编译器是一流的。 GNU 人不喜欢听 MS 工具有多么出色,但这是事实。
  • 我曾经使用 GCC 并且内在函数的优化非常糟糕。 :( 我从来不知道微软的编译器这么好。让我测试一下我的代码,看看它是如何的。
【解决方案3】:

所以这个问题已经有四年了,现在仍然出现在搜索结果中......

2016 年情况好多了。

我从汇编转录为内在函数的许多简单代码现在被编译器优化得比我更好,因为我懒得做管道工作(有多少不同的管道现在?),而编译器只需要我传递正确的--mtune=

对于寄存器分配可能变得紧张的复杂代码,GCC 和 Clang 仍然可以比手写代码慢两倍...或三倍(ish)。它主要是寄存器溢出,所以你应该从你的代码结构中知道这是否有风险。

但他们有时都会发生令人失望的事故。我会说现在这是值得的风险(尽管我是有偿承担风险的),如果你确实被某些东西击中然后提交一个错误。这样事情就会越来越好。

【讨论】:

  • 也许你是对的,编译器现在更好了。但它仍然不够好。它永远不会。正如我上面提到的,只要您了解 NEON,您就可以在内部函数中编写执行良好的例程,不幸的是,网络上充斥着用内部函数编写的乏善可陈的 NEON 示例,尤其是 AOSP 的 NEON 实现是一个糟糕的笑话。这当然是因为他们在没有阅读 ARM 技术参考手册的情况下轻描淡写地编写了这些代码。
  • 2017 年状态更新:我的 asm 4x4 浮点矩阵乘法的运行速度几乎是内部函数版本的三倍,也是我编写的。 (Clang,Android Studio 3.01 内置,构建工具版本 27.0.1,ARM 模式)还是纯属浪费时间。
【解决方案4】:

现在您甚至可以对纯 C 代码进行自动矢量化,并且正确处理内在函数: https://godbolt.org/z/AGHupq

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2016-08-18
    相关资源
    最近更新 更多