试图理解 _mm256_permute2x128_si256 的英特尔内在指南解释

Posted

技术标签:

【中文标题】试图理解 _mm256_permute2x128_si256 的英特尔内在指南解释【英文标题】:Trying to understand Intel Intrinsics Guide explanation for _mm256_permute2x128_si256 【发布时间】:2020-12-04 21:54:00 【问题描述】:

我正在尝试了解 _mm256_permute2x128_si256。是先将寄存器 a 的所有 256 位读入机箱,然后再将寄存器 b 的 256 位读入机箱吗?还是在向量 a 和向量 b 之间交错读取每 32 位?那么哪个向量的哪个 32 位被读取对应于 imm8 中的哪个位以什么顺序以及如何读取?谢谢!

DEFINE SELECT4(src1, src2, control) 
    CASE(control[1:0]) OF
    0:  tmp[127:0] := src1[127:0]
    1:  tmp[127:0] := src1[255:128]
    2:  tmp[127:0] := src2[127:0]
    3:  tmp[127:0] := src2[255:128]
    ESAC
    IF control[3]
        tmp[127:0] := 0
    FI
    RETURN tmp[127:0]

dst[127:0] := SELECT4(a[255:0], b[255:0], imm8[3:0])
dst[255:128] := SELECT4(a[255:0], b[255:0], imm8[7:4])
dst[MAX:256] := 0

【问题讨论】:

CASE(control[1:0]) OF 在 C/C++ 中的读法与 switch(control & 0x3) 类似(但在每种情况下都有隐式的 break)。你在哪里看到伪代码中的 32 位? @chtz 如果 src1 是 256 位向量,在内存中不是表示为寄存器中每 32 位的一个元素吗? @chtz 你是怎么知道在每个开关盒中使用 0x3 来控制 & 的? 【参考方案1】:

请参阅此网站,它比英特尔的文档提供更多信息:

https://www.felixcloutier.com/x86/vperm2i128

【讨论】:

【参考方案2】:

这是一个 shuffle,从 2 个输入向量的 4 个通道中选择两个 128 位通道。 控制整数操作数有两个 2 位字段,每个字段索引 4 个通道之一。您可以将其视为连接两个输入向量,然后索引到该 4 通道数组。

或者如果设置了索引半字节的高位,它会将结果的那个通道归零。

没有什么涉及 32 位粒度。内在函数指南中的伪代码定义了一个辅助函数,并将每个输入的所有 256 位传递给该辅助函数两次。所有[hi:lo] 范围都以位为单位,而不是字节。

英特尔的相应指令的 asm 文档 (vperm2i128) 具有更易于理解的伪代码,用于分隔归零:

CASE IMM8[1:0] of
    0: DEST[127:0]←SRC1[127:0]
    1: DEST[127:0]←SRC1[255:128]
    2: DEST[127:0]←SRC2[127:0]
    3: DEST[127:0]←SRC2[255:128]
ESAC

CASE IMM8[5:4] of
    0: DEST[255:128]←SRC1[127:0]
    1: DEST[255:128]←SRC1[255:128]
    2: DEST[255:128]←SRC2[127:0]
    3: DEST[255:128]←SRC2[255:128]
ESAC

IF (imm8[3])
    DEST[127:0] ← 0
FI
IF (imm8[7])
    DEST[255:128] ← 0
FI

【讨论】:

如果读入控制值 49 (0b0011 0b0001) 是读取当前看起来的小端序还是编译器反向读取的大端序为 0b0100 0b1100? @artVandalay:它是 1 个字节,所以没有正常意义上的字节序。最左边的位是最重要的位 7。 (0 代表49 = 0x31 = 0b0011'0001)。位 [7:4] 控制目标的高通道(将由_mm256_store... 存储到更高地址的通道)。英特尔的向量标准符号和图表将最高元素放在左侧,与我们用于书写数字的标准位值系统一致。 Convention for displaying vector registers / How does endianness work with SIMD registers? 十六进制是控制值的有用表示法,因为它将控制值分成两个 4 位组,有用的值是 0..3 或任何设置高位(8 或更高)的值. 感谢您的解释!

以上是关于试图理解 _mm256_permute2x128_si256 的英特尔内在指南解释的主要内容,如果未能解决你的问题,请参考以下文章

_mm256_loadu2_m128i 内在函数在 g++ 下不可用?

如何访问 256 位 ps 向量的组件

填充__m128i参数的正确方法是啥,从基本类型(例如short)到与_mm256_broadcast_epi(例如_mm_broadcastw_epi16)一起使用

gcc 标头错误:“_mm256_set_m128d”未在此范围内声明

从四个 __m128i 变量的 64 个高位或低位初始化 __m256i

将 __m256i 设置为两个 __m128i 值的值