c - 使用 C 中的英特尔内在函数加载和存储复杂 float

标签 c vector floating-point complex-numbers intrinsics

我正在尝试使用 __m128 对复杂的 float 进行一些计算 vector 单位。与__m128我可以存储两个complex float s,因为每个复数由两个 float 组成,一个实部和一个虚部。

到目前为止,一切顺利。

当我必须将我的答案“收集”到一个中时,我的问题就出现了 complex float 。假设我有两个__m128 vector ,以及存储在这两个 vector 中的四个复数。例如,我可以使用 _mm_add_ps 将两个 vector (两个和两个 float )添加在一起。内在的,但如何将结果 vector 中的两个复数“减少”为一个复数(两个 float )并将其存储在数组中?

同样,如果我想从数组中获取一个复数并将其存储在 vector 内两次(实部在第一个和第三个 block 中,虚部在第二个和第四个 block 中),我该如何做实现这个吗?

最佳答案

如果您想对复数使用 SIMD,首先不要以交错/打包格式存储复数。将实部和虚部存储在单独的数组中,这样您就可以并行执行四个复数乘法,而无需任何洗牌(或像 HSUBPS 这样的缓慢水平操作)。

直接回答问题:do the first stage of a horizontal sum :将高 64 降低到另一个 vector 的低 64(使用 _mm_movehl_ps ),然后 _mm_add_ps,如我对该问题的回答所示。

然后你就可以MOVLPS存储低 2 个 float :void _mm_storel_pi (__m64 *p, __m128 a)。看来你需要烦人的转换才能使用它:/MOVSD 也可以工作,但需要多一个字节来编码。

<小时/>

And similarly, if I want to grab a complex number from my array and store it twice inside a vector

使用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 中的英特尔内在函数加载和存储复杂 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40237649/

相关文章:

c - 在 Visual Studio 中识别项目

c - c语言数组的定义

c++ - 拒绝 std::vector 删除其数据

math - float 学有问题吗?

c - double 和浮点格式显示不同的结果

c - 我想在一个循环或类似的东西中有 100 个结构

c++ - CDT 定制构建

c++ - 空 vector 是其结构的大小吗?

c++ - C++ 中带有 std::vector 的 const

floating-point - 为什么IEEE 754标准使用127偏差?