【发布时间】:2020-12-26 04:16:33
【问题描述】:
我有三个 ymm 寄存器 -- ymm4、ymm5 和 ymm6 -- 包含双精度 (qword) 浮点数:
ymm4: 73 144 168 41
ymm5: 144 348 26 144
ymm6: 732 83 144 852
我想写出上面矩阵的每一列。例如:
-- extract ymm4[63:0] and insert it at ymm0[63:0]
-- extract ymm5[63:0] and insert it at ymm0[127:64]
-- extract ymm6[63:0] and insert it at ymm0[191:128]
所以 ymm0 读取 73、144、732。
到目前为止我用过:
mov rax,4
kmovq k6,rax
vpxor ymm1,ymm1
VEXPANDPD ymm1{k6}{z},ymm6
这会导致 ymm1 读取 [0 0 732],所以我已经完成了第一步,因为 732 是 ymm6 中 [63:0] 处的元素。
对于 ymm4 和 ymm5,我使用 vblendpd:
vblendpd ymm0,ymm1,ymm4,1
这会导致 ymm0 读取 [73 0 732],所以我已经完成了第二步,因为 73 是 ymm4 中 [63:0] 处的元素。
现在我需要将 ymm5[63:0] 放在 ymm0[127:64]:
vblendpd ymm0,ymm0,ymm5,2
这导致 ymm0 读取 [73 144 732],所以现在我完成了第一列 [63:0]。
但是现在我需要对 ymm 寄存器中的第 2、3 和 4 列做同样的事情。在我添加更多说明之前,这是执行我所描述的最有效的方法吗?还有其他更有效的方法吗?
我研究了 unpckhpd (https://www.felixcloutier.com/x86/unpckhpd)、vblendpd (https://www.felixcloutier.com/x86/blendpd 和 vshufpd (https://www.felixcloutier.com/x86/shufpd),我在上面展示的似乎是最好的解决方案,但它有很多指令,并且编码显示在imm8 值的文档有些不透明。有没有更好的方法来提取三个 ymm 寄存器的对应列?
【问题讨论】:
-
您的某些位范围是向后的。
127:64的位置最高,就像 Intel 手册一样。但是0:63是相反的。vunpcklpd看起来像是将 2 个向量的低双精度组合到另一个寄存器的低 128 位的方法。你甚至可以在 AVX512 的合并掩码下执行此操作,如果你有它以避免单独的vpblendd,但你只标记了这个 AVX2。 -
@RTC222 您提供的示例代码确实使用了 AVX-512 指令。仅仅避免
zmm寄存器并不能确保您避免 AVX-512。相反,请确保只使用 AVX2 和更早的指令。 -
我是否正确理解您的最终目标是将 3x4 矩阵转置为 4 个寄存器,每个寄存器 3 个条目?
-
@RTC222。好的。对此存在快速算法,让我为您绘制一些草图。
-
降频基于使用 512 位向量。即使使用 AVX512VL 256 位向量也很好,就像您对屏蔽的 256 位随机播放所做的那样。由于它们是“轻量级”指令,不在 FMA 单元上运行,它们根本不应该影响涡轮时钟:SIMD instructions lowering CPU frequency。但正如 fuz 指出的那样,您确实没有避免使用 AVX512。
VEXPANDPD和kmovq只存在于 AVX512 中,{k1}屏蔽是 AVX512 的功能,甚至k1寄存器本身也只存在于 AVX512 中!
标签: assembly x86-64 nasm avx avx2