在 C 中使用英特尔内在函数加载和存储复杂的浮点数
Posted
技术标签:
【中文标题】在 C 中使用英特尔内在函数加载和存储复杂的浮点数【英文标题】:Load and store complex floats with Intel intrinsics in C 【发布时间】:2016-10-25 10:32:36 【问题描述】:我正在尝试使用__m128
向量单位对复数浮点数进行一些计算。使用__m128
,我可以存储两个complex float
s,因为每个复数由两个浮点数组成,一个实部和一个虚部。
到目前为止,一切都很好。
当我必须将我的答案“收集”到 one complex float
时,我的问题就出现了。假设我有两个 __m128
向量,以及存储在这两个向量中的四个复数。例如,我可以使用 _mm_add_ps
内在函数将两个向量(两个和两个浮点数)相加,但是如何将结果向量中的两个复数“减少”为一个复数(两个 float
s)和将其存储在数组中?
同样,如果我想从我的数组中获取一个复数并将其存储在一个向量中两次(实部在第 1 块和第 3 块中,虚部在第 2 块和第 4 块中),我该怎么做完成这个?
【问题讨论】:
【参考方案1】:如果您想在复数上使用 SIMD,请首先不要以交错/压缩格式存储复数。将实部和虚部存储在单独的数组中,这样您就可以并行执行四次复数乘法运算,而无需任何改组(或像 HSUBPS 这样的慢速水平运算)。
直接回答这个问题:做the first stage of a horizontal sum:将高64降低到另一个向量的低64(使用_mm_movehl_ps
),然后_mm_add_ps
,就像我对该问题的回答所示。
然后您可以MOVLPS 存储低 2 个浮点数:void _mm_storel_pi (__m64 *p, __m128 a)
。看起来你需要烦人的转换才能使用它:/ MOVSD 也可以工作,但需要多一个字节来编码。
同样,如果我想从我的数组中获取一个复数并将其存储在一个向量中两次
使用MOVDDUP 从内存或其他寄存器广播 64 位。您需要进行一些强制转换才能使用内在函数,但这很好(它们不会编译为任何指令,并且在 float
数据上使用诸如 MOVDDUP 之类的 double
指令不会对任何现有 CPU 造成任何损失):
__m128d _mm_loaddup_pd(double const * dp);
__m128d _mm_movedup_pd(__m128d a);
与 PMOVZX (this design flaw is one of my major pet peeves with intrinsics) 不同,至少它具有负载固有特性。
【讨论】:
以上是关于在 C 中使用英特尔内在函数加载和存储复杂的浮点数的主要内容,如果未能解决你的问题,请参考以下文章
在 C 中存储和使用具有 1,000,000 位有效数字的浮点数的最有效方法是啥?