如何将 4 个 32 位浮点数存储到一个 128 位 xmm 寄存器中?
How to store 4 32 bit floats into one 128 bit xmm register?
我想将 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 可能会有所帮助,但是否有更好的解决方案来解决我的问题?
查看 compiler output for _mm_set_ps(f3,f2,f1,f0)
或 _mm_setr_ps(f0,f1,f2,f3)
,选择曲调和 -march
选项。
或者看看 Agner Fog's optimization guide:他有一个关于 SSE/AVX 的章节,其中有一个方便的 table 的 data-movement 指令类型。非常适合学习如何在高度 non-orthogonal SSE/AVX 扩展中使用哪些随机播放。
正如人们所指出的,标准方法是 2x unpcklps
将对合并到 [00ba]
[00dc]
的向量中,其中 0
是一个 don't-care 值或实际上 0.0
如果你的标量浮点数的上部元素恰好为零。 (我的表示法遵循图表中的英特尔约定,即高元素位于 左侧 ,因此左移将数据移动到表示法的左侧,并查看具有不同元素宽度的数据'改变你的写作方式。)
然后movlhps
将一个xmm寄存器的低位qword复制到另一个xmm寄存器的高位qword(合并到现有值)。
如果这对您来说不是显而易见的 well-known,您应该使用 C 语言编写内在函数,并查看优化的编译器输出以了解基本方法。 clang 有一个非常好的 shuffle 优化器,可以找到更好的方法将你的内在逻辑实现到 asm 中。
可能有更好的方法:
这 3 条指令都是随机播放,在 Intel Sandybridge-family CPU 上每个时钟吞吐量限制为 1 个(竞争端口 5)。
如果我们有 SSE4.1 可用于 blendps
(立即 blend-control),我们可以将其用作最后一步而不是随机播放。它可以 运行 在任何端口上。
我认为我们可以使用 shufps
来创建 [0c0a]
和 [d0b0]
的向量。 shufps
输出的低2个元素来自第一个source=dst操作数,另一半来自另一个source.
如果您的输入向量实际上 zero-extended 并且绝对没有高垃圾,您可以使用 SSE1 orps
而不是混合来获得 [dcba]
我想将 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 可能会有所帮助,但是否有更好的解决方案来解决我的问题?
查看 compiler output for _mm_set_ps(f3,f2,f1,f0)
或 _mm_setr_ps(f0,f1,f2,f3)
,选择曲调和 -march
选项。
或者看看 Agner Fog's optimization guide:他有一个关于 SSE/AVX 的章节,其中有一个方便的 table 的 data-movement 指令类型。非常适合学习如何在高度 non-orthogonal SSE/AVX 扩展中使用哪些随机播放。
正如人们所指出的,标准方法是 2x unpcklps
将对合并到 [00ba]
[00dc]
的向量中,其中 0
是一个 don't-care 值或实际上 0.0
如果你的标量浮点数的上部元素恰好为零。 (我的表示法遵循图表中的英特尔约定,即高元素位于 左侧 ,因此左移将数据移动到表示法的左侧,并查看具有不同元素宽度的数据'改变你的写作方式。)
然后movlhps
将一个xmm寄存器的低位qword复制到另一个xmm寄存器的高位qword(合并到现有值)。
如果这对您来说不是显而易见的 well-known,您应该使用 C 语言编写内在函数,并查看优化的编译器输出以了解基本方法。 clang 有一个非常好的 shuffle 优化器,可以找到更好的方法将你的内在逻辑实现到 asm 中。
可能有更好的方法:
这 3 条指令都是随机播放,在 Intel Sandybridge-family CPU 上每个时钟吞吐量限制为 1 个(竞争端口 5)。
如果我们有 SSE4.1 可用于 blendps
(立即 blend-control),我们可以将其用作最后一步而不是随机播放。它可以 运行 在任何端口上。
我认为我们可以使用 shufps
来创建 [0c0a]
和 [d0b0]
的向量。 shufps
输出的低2个元素来自第一个source=dst操作数,另一半来自另一个source.
如果您的输入向量实际上 zero-extended 并且绝对没有高垃圾,您可以使用 SSE1 orps
而不是混合来获得 [dcba]