vpbroadcastq zmm26{k5}{z},rax
是一个有趣的 hack;如果它有效运行,可能会很有用。特别是使用合并屏蔽作为vmovq
/的替代品vpinsrq
。
vpbroadcastq
除了元素 0 或 1: vmovq rax, xmm26
或之外,没有与 的 (ab) 使用相反的单指令vpextrq rax, xmm26, 1
。是的,在 AVX512F 和 AVX512DQ 中,这些指令分别有 EVEX 编码,可以让它们访问 xmm16-31。如果您的数据在 xmm0-15 中,则可以使用较短的 VEX 编码版本。
但是,您可以VPCOMPRESSQ zmm1/m512 {k5}{z}, zmm26
使用与用于vpbroadcast
. 但它不如其他选项快,因此唯一的优点是使用相同的掩码寄存器作为随机播放控件,如果您不能将设置提升到循环之外,可以节省工作量。
在 KNL 上,VPCOMPRESSQ
(带有寄存器目标)每 3 个周期有一个吞吐量(根据Agner Fog的测试)。 在 Skylake-AVX512 上,它是每 2 个周期一个,延迟为 3c。这两个 CPUvpermq
每个周期运行 1 次,因此它对其他指令的干扰可能较小。我还没有找到vpcompressq
.
在没有存储/重新加载的情况下转到另一个方向需要至少一个 shuffle uop,以及一个单独的 uop 从向量复制到 GP 寄存器(如vmovq
)。(如果您最终想要所有元素,则存储/重新加载可能比纯 ALU 策略更好。前一个或两个 ALU 可能很好,因此您拥有低延迟的它们,因此可以开始一些相关操作)。
如果您的值在 128b“通道”(即偶数元素)的低 64b 中,那么vextracti64x2 xmm1, zmm26, 3
/vmovq rax, xmm1
对于单个元素来说是尽可能高效的。奇怪的名字是因为 AVX512 版本vextracti128
有两种掩码粒度。如果您想要的元素在 zmm0-15 的第 2 个 128b 通道中,则可以通过使用vextracti128 xmm1, ymm6, 1
(仅 3 字节 VEX 前缀用于 AVX2 指令,而不是 4 字节 EVEX)来节省代码大小。
但是,如果您的值在车道的上部 64b 中(即奇数元素,从 0 开始计数),则您需要,vpextrq rax, xmm, 1
而不是vmovq
,并且它(在 Skylake 上)解码为 shuffle uop 和vmovq
uop。(永远不要使用vpextrq rax, xmm, 0
,因为它浪费了一个 shuffle uop。这就是编译器优化_mm_extract_epi64(v, 0)
为 a 的原因vmovq
。)
对于奇数元素,您仍然可以使用vpermq zmm1, zmm2, zmm3/m512/m64bcst
+vmovq
一次随机播放。如果您需要在循环中提取,请在循环外设置一个随机播放向量常量。或者,如果您仍然需要其他常量(因此您的函数已经有一个常量的热缓存行),如果不在循环中,广播加载内存操作数应该没问题。
vpermq
+vmovq
也适用于索引不是编译时常量的情况,因为您在 shuffle 控制向量中需要的只是将索引放在元素 0 中。例如vmovd xmm7, ecx
为vpermq zmm1, zmm2, zmm7
/设置vmovq rax, zxm1
正如@Bee 所说,如果您需要多个元素,存储/重新加载是一个不错的选择。如果您需要一个运行时变量元素,您也可以使用它,因为从对齐的 512b 存储到对齐的 64b 重新加载的存储转发可能不会停止。(仍然比vpermq
解决方案更高的延迟,但只使用内存微指令,而不是 ALU。ALU 微指令在 Skylake-AVX512 中可能非常重要,其中端口 1 不会运行任何向量微指令,而有 512b 微指令正在运行。)
如果您的元素编号是编译时常数,您可以使用vextracti64x2 [rsp-16], zmm26, 3
. (或者vextracti128
如果它是通道 1。)如果您最终想要内存中的值,您可以使用仅设置第 2 位的掩码寄存器来仅存储高元素。(但是 IDK 如果额外的屏蔽部分进入未映射的页面,它的性能如何。IIRC,它实际上并没有故障,但从微架构上来说,处理它可能会很慢。即使跨越 128b 完整的缓存线边界宽度可能很慢。)
AVX2VEXTRACTI128 [mem], ymm, 1
指令在 Skylake 上作为(非微融合)存储运行,没有随机播放端口(http://agner.org/optimize/)。AVX512 extract-to-memory 希望是相同的,仍然没有使用 shuffle uop。(吞吐量/延迟 Instlatx64 数字可用,但我们不知道什么与什么竞争哪些吞吐量资源,所以它比 Agner Fog 的指令表有用得多。)
对于 KNL,VEXTRACTF32X4 [mem], zmm
是 4 uops,吞吐量很差,和 AVX2vextracti128 [mem], ymm, imm8
一样。所以(假设存储转发运行良好)只需将整个 512b 向量存储在 KNL 上。