我想使用 neon 指令 SIMD 和臂组件来计算 4 个点的大小和角度。大多数语言都有一个内置库,在我的例子中是 C++,它计算角度 (atan2),但仅针对一对浮点变量(x 和 y)。我想利用处理 q 寄存器的 SIMD 指令来计算 4 个值向量的 atan2。
精度要求不高,速度更重要。
<小时/>我已经有一些汇编指令可以计算 4 个浮点寄存器的大小,对于我的应用程序来说具有可接受的精度。 q1 包含 4 个“x”值(x1、x2、x3、x4)。 q2 包含 4 个“y”值(y1、y2、y3、y4)。 q7 包含 4 个结果的大小 (x1^2 + y1^2、x2^2 + y2^2、x3^2 + y3^2、x4^2 + y4^2)。
vmul.f32 q7, q1, q1
vmla.f32 q7, q2, q2
vrecpe.f32 q7, q7
vrsqrte.f32 q7, q7
使用 SIMD 指令计算两个向量的近似 atan2 的最快方法是什么?
最佳答案
参见math-neon对于现有的单值浮点实现。由于它没有(或很少)条件,因此它应该可以很好地转换为 SIMD 实现。
由于 ARM NEON 没有直接计算此值的指令,因此有多种技术可以创建比泰勒级数更好的近似值。具体来说,最小-最大方法给出了一个很好的近似多项式候选。 min-max指的是最小化最大误差;与 Chebyshev approximation通常都非常好。
DSP guru详细说明了函数逼近的不同方法。网上还有大量书籍。您可以使用matlab、octave或其他一些工具包搜索最佳多项式。通常,您需要将其与范围和精度绑定(bind)。一旦您对单个值有了良好的算法,将其扩展到任何类型的SIMD应该是微不足道的。
问题calculate atan2引用 Apple's atan.c来源。代码中的系数很可能源 self 上面给出的内容。此代码的问题是它无法扩展到 SIMD,并且 atan()
近似是分段的,并且根据范围需要不同的系数。对于您的 SIMD,您将需要在整个范围内使用相同的系数(乘数、除数、方程)。
Abramowitz and Stegun: Handbook of Mathematical Functions有一个关于循环函数的章节,第 4.4.28 节给出了对数公式。这似乎类似于 eglibc实现。
关于assembly - 使用 ARM NEON 汇编对 atan2 进行 SIMD 向量化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18187492/