ped*_*zer 3 x86 assembly sse x86-64 simd
我想将4个32位浮点数存储到xmm0中,其中每个浮点数都存储在一个128位寄存器中。例如,我有4个浮点数:xmm1:10.2 xmm2:5.8 xmm3:9.3 xmm4:12.7(每个仅使用128位寄存器中的32位),并希望将它们像这样存储到xmm0中:10.2、5.8、9.3、12.7这样它们存储在xmm0内部。
然后,在对xmm0做一些数学运算(例如,mulps ..)后,我还想分别提取它们中的每一个。
我尝试使用movlps和movhps,但它们仅使用内存进行加载,而不使用128位寄存器作为源。由于性能,我不想使用任何其他内存。
PSLLDQ可能会有所帮助,但是对于我的问题有更好的解决方案吗?
_mm_set_ps(f3,f2,f1,f0)
_mm_setr_ps(f0,f1,f2,f3)
选择或不选择调整和-march
选项,查看编译器输出。
或看看Agner Fog的优化指南:他有一章关于SSE / AVX,其中有按类型列出的方便的数据移动指令表。非常适合学习如何在高度非正交的SSE / AVX扩展中使用随机播放。
正如人们所指出的那样,标准方法是2x将对unpcklps
合并成向量,[00ba]
[00dc]
其中向量0
是“无关”值,或者实际上0.0
标量浮点数的高位元素恰好为零。(我的符号法遵循Intel约定,图中的元素左侧为高,因此左移将数据以符号的形式向左移动,而查看具有不同元素宽度的数据不会改变其编写方式。)
然后movlhps
将一个xmm寄存器的低位qword复制到另一个xmm寄存器的高位qword(合并到现有值中)。
如果这不是很明显并且不为您所熟知,则应该使用具有内在函数的C语言编写代码,并查看经过优化的编译器输出以了解基本方法。clang有一个非常好的shuffle优化器,可以找到更好的方法来将内部函数的逻辑实现为asm。
这3条指令都是随机的,在Intel Sandybridge系列CPU上,每个时钟吞吐量限制为1个(与端口5竞争)。
如果我们有可用的SSE4.1 blendps
(具有即时混合控件),则可以将其用作最后一步而不是随机播放。它可以在任何端口上运行。
我认为我们可以shufps
用来创建[0c0a]
和的向量[d0b0]
。shufps
输出的低2个元素来自第一个source = dst操作数,另一半来自另一个源。
如果您的输入向量实际上是零扩展且绝对没有高垃圾,则可以使用SSE1 orps
而不是blend来获得[dcba]