assembly - 在混合上下文中选择 SSE 指令执行域

标签 assembly vector sse

我正在使用一些 SSE 汇编代码,其中没有足够的 xmm 寄存器来同时将所有临时结果和有用的常量保留在寄存器中。

作为一种解决方法,对于某些具有相同分量的常量向量,我将多个向量“压缩”到单个 xmm 寄存器中,即下面的 xmm14。我使用 pshufd 指令来解压缩我需要的常量向量。该指令有一点延迟,但由于它需要源寄存器和目标寄存器,所以在其他方面非常方便:

…
Lfour_15_9:
    .long 4
    .long 1549556828
    .long 909522486
    .long 0
…
    movdqa  Lfour_15_9(%rip), %xmm14
…
    pshufd  $0, %xmm14, %xmm4
    paddd   %xmm4, %xmm3
…
    pshufd  $0b10101010, %xmm14, %xmm5
…
    pshufd  $0b10101010, %xmm14, %xmm5
…
    pshufd  $0b01010101, %xmm14, %xmm5
    xorps   %xmm5, %xmm2    
    movaps  %xmm5, 112(%rax)

上面的代码采用gas/AT&T语法,我的目标是从Core 2到Westmere的Intel处理器,它们提供高达SSSE3的指令。

Agner Fog's manuals 之一指出对于某些用途,使用具有错误“类型”的向量指令可能是有利的。例如,即使移动的数据不是浮点型,memcpy 也有利于使用 movaps 指令进行写入,因为 movaps 短>movdqa,可在更多处理器上使用,并且由于它不使用数据进行计算,因此有关次正规的常见警告都不适用。对于打乱单词也给出了相同的建议(我之前链接到的手册中的第 13.2 和 13.3 节)。

我的情况有点特殊,因为我的目标是重构常量向量,如果需要,有些向量可以仅与单精度“类型”指令一起使用:这些仅在 movaps 中涉及>、shufpsxorps 计算。并且一些常量向量必须参与只能使用整数类型指令完成的计算:paddd(因此我可以使用movdqapshufdpxor 指令(根据需要保留在整数执行域中)。

这个问题的一般版本是:考虑到我的目标是 Core 2 和 Westmere 之间的 Intel 处理器,我应该分别使用什么类型的指令从内存(重新)加载 xmm14 到将其解压缩到只能看到单精度计算的寄存器,将其解压缩到将看到一些无法使用单精度指令完成的计算的寄存器,以及对于那些可以使用单精度指令完成的操作后一种情况?

<小时/>

编辑:这一点下面的问题部分由哈罗德在评论中回答。

<小时/>

一般问题中包含一个更具体的子问题:当我用浮点指令(例如 movdqa 指令)随机替换某些整数执行域指令时,有人能解释为什么吗?通过movaps指令),函数会计算错误吗?我预计唯一的后果是执行延迟,而不是错误的结果。

例如,如果在上面我仅将 pshufd $0, %xmm14, %xmm4 指令更改为 shufps 指令,则计算将完全错误( >xmm4是后面paddd涉及到的寄存器)。更改其他指令而不是该指令会导致其他类型的错误。

最佳答案

对于xor之类的东西更喜欢整数域指令。在 Intel CPU 上,只有一个执行端口可以处理 FP 域逻辑(XORPS 等),但大多数执行单元(在 SnB 到 Haswell 上:p015,但不是 Haswell 的端口 6)可以处理向量整数逻辑指令 (PAND/POR/PXOR)。

根据 Agner Fog 的测试,如果需要将 FP 域指令的结果作为向量整数域指令的输入,有时会花费额外 1 个周期的延迟。 (请参阅微架构文档)。这适用于 AMD 和英特尔。仅当指令位于关键路径上时这才重要。 (循环中最长的 dep 链)。

正确性不是问题,除非您发现指令的非正交性使您陷入困境。 shufps 的作用与 pshufd 不同。我认为,vpermilps ymm, ymm, imm 确实与 pshufd 做同样的事情,并且似乎只是为了将随机播放与内存加载相结合而引入的。 (否则,您可以仅使用 AVX 版本的 shufps 以及与两个源相同的寄存器,并获得相同的行为)。

我不知道是否有人彻底测试了使用较短指令编码 ...ps 版本不会产生额外延迟的所有情况。不过,SnB 和更高版本的 Intel CPU 中的 uop 缓存使得内部循环不再是一个问题。 (指令解码只是第一次循环时的瓶颈。)

编辑:除了 uop-cacheline 边界,如果您的代码可以维持完整的 4 uop/周期,则这可能是瓶颈。 IDK 是否有任何工具可以帮助对齐 x86 指令,以便 uop 缓存行保存 4 uop 的倍数。

关于assembly - 在混合上下文中选择 SSE 指令执行域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28660698/

相关文章:

c++ - 如何在 OpenMP 4 中为 std::vector 写入 "target data map"?

c - 最佳 SSE 无符号 8 位比较

c++ - x86汇编指令优化

windows - 二进制文件(PE/COFF 和 ELF)格式和术语的说明

c - __stack_size__, __stack_end__ 符号在 'C'

linux - ELF 标准和重定位偏移量计算

c++ - 如何检索 vector 中第一个找到的具有最低值的元素

assembly - ROL AX,8 是 NOP,对吧?

arrays - 在 AS3 中使用值数组初始化 Vector 是否会部分违背 Vector 的目的?

c++ - C/C++ : -msse and -msse2 Flags do not have any effect on the binaries?