SIMD使用ARM NEON程序集对atan2进行矢量化

时间:2013-08-12 12:53:07

标签: assembly arm vectorization neon atan2

我想用霓虹灯指令SIMD和手臂组装计算4点的大小和角度。在大多数语言中都有一个内置库,在我的例子中是C ++,它计算角度(atan2),但只计算一对浮点变量(x和y)。我想利用处理q寄存器的SIMD指令来计算atan2的4个值的向量。

要求精度不高,速度更重要。


我已经有一些汇编指令来计算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的最快方法是什么?

1 个答案:

答案 0 :(得分:6)

有关现有的单值浮点实现,请参阅math-neon。由于它没有(或很少)条件,它应该很好地转换为 SIMD 实现。

由于ARM NEON没有直接计算的指令,因此有多种技术可以创建比泰勒级数更好的近似值。具体来说, min-max 方法为近似提供了一个很好的多项式候选。 min-max 是指最小化最大误差; Chebyshev approximation通常非常好。

DSP guru具有函数逼近的不同方法的细节。网上也有很多书。您可以使用 matlab octave 或其他工具包搜索最佳多项式。通常,您需要使用范围精度绑定它。一旦你有一个单一值的好算法,将其扩展到任何类型的 SIMD 应该是微不足道的。

问题calculate atan2引用了Apple's atan.c来源。代码中的系数很可能来自我上面给出的内容。此代码的问题是它不能扩展到 SIMD ,因为atan()近似是分段的,并且根据范围需要不同的系数。对于 SIMD ,您需要在整个范围内使用相同的系数(乘数,除数,等式)。

Abramowitz and Stegun: Handbook of Mathematical Functions有一章关于循环函数,第4.4.28节给出了对数公式。这似乎与eglibc实现类似。