【问题标题】:Is there a benefit (other than convenience) to ARM NEON array types?ARM NEON 数组类型有什么好处(除了方便)吗?
【发布时间】:2021-04-17 17:15:10
【问题描述】:

ARM NEON C 内部函数定义数组类型 (per docs here),它们是包含向量数据类型数组的 C 结构。例如,int16x4x2_t 是两个int16x4_t

我的问题很简单:为什么会存在这些?与直接使用向量类型相比,它们是否具有一些性能优势?例如,如果我从双指针 vld1q_f64float64x2_t 并使用 vaddq_f64vmulq_f64vfmaq_f64 等,我会期望与 vld1q_f64_x4-ing 和 float64x2x4_t 有任何性能差异并在数组元素上使用相同的函数。我想我只是对为什么他们创建这些固定长度的数组类型感到困惑,而直接对它们进行操作的唯一内在函数是加载和存储。

【问题讨论】:

    标签: c optimization arm neon


    【解决方案1】:

    它们不仅仅用于加载和存储;当有多个 128 位输出向量时使用它们。例如,请参阅vuzp_* / vuzpq_*

    这是一种包装操作的好方法,这些操作需要多个向量,而无需使用指针,这很容易搞砸。这包括在单个操作中加载/存储多个向量的加载和存储。例如,可能可以将 vld4_s8 函数实现为:

    void vld4_s8(int8x8_t* a, int8x8_t* b, int8x8_t* c, int8x8_t* d, int8_t* data);
    

    如果我看到该签名,我将不得不查找一些文档来确定 WTF 是否使用前四个参数进行。它们是输入还是输出?它们是指向向量数组的指针,还是只是一个向量?它们是否都需要设置,或者如果我不需要该值,我可以/应该传递 NULL 吗?

    另一方面,当前函数很难出错。有一个输入是一个 8 位整数数组,它返回一个由四个向量组成的数组。我唯一会做的不同是将a conformant array parameter 用于输入数据,以便您确切知道它需要多少元素,但这在 C++ 或 MSVC 中不起作用(可能直到几个月前他们添加C99/C11 支持)。

    我是否会期望 vld1q_f64_x4-ing 一个 float64x2x4_t 并在数组元素上使用相同的函数有任何性能差异。

    可能,但不是来自乘法。优势在于使用一条指令来加载所有四个向量;例如,参见https://godbolt.org/z/aY8a95。在这种情况下,您有一个负载和四个乘法,而不是四个负载和四个乘法。

    在实践中,我怀疑大多数优秀的编译器都能够将其优化为相同的代码(尽管我想检查一下),但内部函数通常与指令 1:1 映射,因此您不必信任编译器变聪明。在这种情况下,有一个 ld4 指令,所以有一个 vld4_* 系列函数,这些类型在这些 API 中使用。

    【讨论】:

    • 太棒了,非常感谢。感谢您的清晰描述。
    • 通常像float64x2x4_t 这样的类型会受到“同构向量聚合数据类型 (HVA)”的优化,编译器可以将其分解为一组单独的寄存器。
    猜你喜欢
    • 2011-10-20
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    • 2013-09-16
    • 2021-11-27
    • 1970-01-01
    • 2017-06-08
    相关资源
    最近更新 更多