【发布时间】:2019-11-16 04:21:12
【问题描述】:
我想将 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 可能会有所帮助,但我的问题是否有更好的解决方案?
【问题讨论】:
-
PSLLD不会像您认为的那样做。它不会移动双字本身,它会移动每个双字内的位。请改用SHUFPS或PSLLDQ。 -
I asked GCC and clang to do it。他们将
xmm1..4合并为xmm0。两者都使用 3 条指令,每条指令都应使用端口 5 和 1c lat/tput(但我只浏览了 Agner Fog 的表格并且仅适用于 SklX)。但是如果我没记错的话,gcc one 只使用 SSE 扩展。 -
unpcklps和movlhps可以将内存或其他寄存器作为第二个参数。如果您不需要 AVX 指令,只需获取@MargaretBloom 的链接并将-march=cannonlake替换为-msse(或-msse4.2,或您喜欢的任何指令集):godbolt.org/z/ruhVhl -
@MargaretBloom:我不知道有什么方法可以用 SSE/AVX2 击败 3 端口 5 微指令。到目前为止,最明显的方法是 2x
unpcklps+unpcklpd或movlhps。但是既然你提到了它,如果你可以使用shufps将你的输入输入到[abxx][xxcd],或者实际上可能:[axcx][xbxd](因为 shufps 输出的低 2 个元素来自第一个 source=dst,另一半来自另一个源。)x86-64 GCC 默认使用基线 x86-64,即 SSE1 + SSE2。跨度> -
@pedzer:查看
_mm_set_ps(f3,f2,f1,f0)的编译器输出。或者查看 Agner Fog 的优化指南:他有一章是关于 SSE/AVX 的,其中有一个方便的按类型列出的数据移动指令表。 agner.org/optimize
标签: assembly x86 x86-64 sse simd