【问题标题】:Broadcast a word to an xmm register广播一个词到一个 xmm 寄存器
【发布时间】:2019-07-11 14:33:59
【问题描述】:

我需要将一个 16 位字移动八次到 xmm 寄存器中以进行 SSE 操作

E. g.: 我想将 16 位字 ABCD 处理到 xmm0 寄存器,这样最终结果看起来像

ABCD | ABCD | ABCD | ABCD | ABCD | ABCD | ABCD | ABCD

我想这样做以便稍后使用paddw 操作。到目前为止,我已经找到了 pushfd 操作,它可以做我想做的事情,但只适用于双字(32 位)。 pshufw 仅适用于 - 如果我没记错的话 - 64 位寄存器。是否有我正在寻找的操作,还是我必须以某种方式使用多个 pshufw 来模拟它?

【问题讨论】:

  • 您的目标是哪个 SSE 版本?
  • 另外,如果您只想做一个 paddw 并且您的输入/输出在内存中不是连续的,那么使用标量指令添加它们可能会更好。
  • @Jester 之后我将通过paddw 指令循环。
  • 如果你的ABCD是一个常量你可以做mov eax, 0xABCDABCD; movd xmm0, eax; pshufd xmm0, xmm0, 0显然你也可以从内存中加载它。
  • movd xmm0, ecx; pshuflw xmm0, xmm0, 0; pshufd xmm0, xmm0, 0。或者imul ecx, ecx, 0x00010001; movd xmm0, ecx; pshufd xmm0, xmm0, 0(假设ecx 的前16 位为零)。注意我没有检查延迟和吞吐量,只是抛出想法:)

标签: assembly x86 sse


【解决方案1】:

您可以通过执行随机播放然后解包来实现所需的目标。在 NASM 语法中:

    # load 16 bit from memory into all words of xmm0
    # assuming 16-byte alignment
    pshuflw xmm0, [mem], 0 # gives you [ M, M, M, M, ?, ?, ?, ? ]
    punpcklwd xmm0, xmm0   # gives you [ M, M, M, M, M, M, M, M ]

请注意,这会从 mem 读取 16 个字节,因此需要 16 个字节对齐

实际上只使用了前 2 个字节。如果该数字不在内存中,或者您不能保证可以读到末尾,请使用以下内容:

    # load ax into all words of xmm0
    movd      xmm0, eax                  ; or movd xmm0, [mem]  4-byte load
    pshuflw   xmm0, xmm0, 0
    punpcklwd xmm0, xmm0

使用 AVX2,您可以使用 vpbroadcast* 广播负载或来自寄存器源的广播。如果你愿意,目的地可以是 YMM。

    vpbroadcastw  xmm0, [mem]            ; 16-bit load + broadcast

或者

    vmovd         xmm0, eax
    vpbroadcastw  xmm0, xmm0

1 或 2 字节元素的内存源广播仍会在 Intel CPU 上解码为 load+shuffle uop,但 4 字节或 8 字节块的广播负载甚至更便宜:在加载端口中处理,没有需要随机播放。

无论哪种方式,这仍然比没有 AVX2 或 SSSE3 pshufb 的 2 个单独的随机播放便宜。

【讨论】:

  • 您和@Jester 对imul ecx, ecx, 0x00010001; movd xmm0, ecx; pshufd xmm0, xmm0, 0 的建议都非常有效。我应该选择哪一个?性能有什么区别吗?
  • 令人惊讶的是,imul 在我看过的 CPU 上的延迟为 3,而 pshuflw 只有 1。
  • @Jester:是的,这是在 shuffle 端口上的延迟和执行端口压力之间的权衡。英特尔 Haswell 和更高版本的每个时钟只有 1 个 shuffle 吞吐量(仅限端口 5),因此如果您进行大量 shuffle,这可能是个问题。作为在其他端口上运行的微指令的设置,这很好。当您考虑到工作量时,3c 的乘法延迟(以及 1c 完全流水线的吞吐量)确实非常好。 AMD Bulldozer 系列的 32 位乘法延迟为 4c,而 64 位乘法的延迟为 6c,两者都不是完全流水线的。
猜你喜欢
  • 1970-01-01
  • 2011-01-02
  • 2011-01-14
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 2013-02-03
相关资源
最近更新 更多