C 具有复数的氖本质

C 具有复数的氖本质,c,gcc,arm,neon,C,Gcc,Arm,Neon,我有很多关于复数的计算(通常是一个数组,其中包含一个由两个浮点数组成的结构来表示im和re;见下文),我想用NEON C intrinsic来加速它们。如果你能给我举个例子,告诉我如何加速这样的事情,那就太棒了: for(n = 0;n < 1024;n++,p++,ptemp++){ // get cir_abs, also find the biggest point (value and location). abs_squared = (Uns32)(((Int32)(p

我有很多关于复数的计算(通常是一个数组,其中包含一个由两个浮点数组成的结构来表示im和re;见下文),我想用NEON C intrinsic来加速它们。如果你能给我举个例子,告诉我如何加速这样的事情,那就太棒了:

for(n = 0;n < 1024;n++,p++,ptemp++){  // get cir_abs, also find the biggest point (value and location).
    abs_squared = (Uns32)(((Int32)(p->re)) * ((Int32)(p->re)) 
                  + ((Int32)(p->im)) * ((Int32)(p->im)));
    // ...
}

我已经阅读了“ARM C语言扩展”的第12章,但在理解如何在这里加载和存储我的类型的构造以对其进行计算时仍然存在问题。

使用
vld2*
内部函数在加载时将
re
im
拆分为不同的寄存器,然后分别处理它们,例如

Complex array[16];

const int16x8x2_t vec_complex = vld2q_s16((const int16_t*)array);
const int16x8_t vec_re = vec_complex.val[0];
const int16x8_t vec_im = vec_complex.val[1];
const int16x8_t vec_abssq = vmlaq_s16(vmulq_s16(vec_re, vec_re), vec_im, vec_im);
对于上述代码,Clang3.3生成

vld2.16 {d18, d19, d20, d21}, [r0]
vmul.i16 q8, q10, q10
vmla.i16 q8, q9, q9

使用
vld2*
intrinsic在加载时将
re
im
拆分为不同的寄存器,然后分别处理它们,例如

Complex array[16];

const int16x8x2_t vec_complex = vld2q_s16((const int16_t*)array);
const int16x8_t vec_re = vec_complex.val[0];
const int16x8_t vec_im = vec_complex.val[1];
const int16x8_t vec_abssq = vmlaq_s16(vmulq_s16(vec_re, vec_re), vec_im, vec_im);
对于上述代码,Clang3.3生成

vld2.16 {d18, d19, d20, d21}, [r0]
vmul.i16 q8, q10, q10
vmla.i16 q8, q9, q9

我认为它更适合在另一个StackExchange站点上发布,例如
code Review
。这样做:我认为它更适合在另一个StackExchange站点上发布,例如
code Review
。这样做:谢谢,似乎是我正在搜索的东西。然而,我会用它产生溢出,不是吗?因此,我可能会使用int32x4类型执行所有操作。您可以类似地访问
int16x4_t
部分
int16x8_t
并使用
vaddl_s16
/
vmull_s16
/
vmlal_s16
生成4个32位结果
int32x4_t
(请注意,此操作输入64位SIMD寄存器并输出128位SIMD寄存器)。例如,
const int32x4_vec_abssq_lo=vmlal_s16(vmull_s16(vget_low_s16(vec_re)、vget_low_s16(vec_re))、vget_low_s16(vec_im)、vget_low_s16(vec_im))
不幸的是,带有霓虹灯内部集成电路的环路所需的时间甚至比“unNEONified”还要长循环。存储操作是最耗时的。没有存储的循环需要0,39个us,而存储12,4个us…是否有任何改进的可能性?展开以隐藏延迟。谢谢,似乎是我一直在搜索的东西。但是我会用它产生溢出,不是吗?所以我可能会用int32x4类型做所有事情。你可能会喜欢大致访问
int16x4_t
部分
int16x8_t
并使用
vaddl_s16
/
vmlal_s16
生成4个32位结果
int32x4_t
(注意,此操作输入64位SIMD寄存器并输出128位SIMD寄存器)。例如
const int32x4 vmu t vec=abssq\s16(vget_low_s16(vec_re)、vget_low_s16(vec_re))、vget_low_s16(vec_im)、vget_low_s16(vec_im));
不幸的是,霓虹灯内部的循环比“未初始化”的循环耗时更长循环。存储操作是最耗时的。没有存储的循环需要0,39 us,存储12,4 us…是否有可能改善此情况?展开以隐藏延迟。