【发布时间】:2017-12-23 09:26:33
【问题描述】:
英特尔的内在函数指南 lists a number of intrinsics 用于 AVX-512 K* 掩码指令,但似乎缺少一些:
- KSHIFT{左/右}
- KADD
- KTEST
英特尔开发人员手册声称内部函数不是必需的,因为它们是由编译器自动生成的。但是如何做到这一点?如果这意味着可以将 __mmask* 类型视为常规整数,那将很有意义,但测试 mask << 4 之类的东西似乎会导致编译器将掩码移动到常规寄存器,移动它,然后移回一张面具。这是使用 Godbolt 的最新 GCC 和带有 -O2 -mavx512bw 的 ICC 测试的。
另外有趣的是,内在函数只处理 __mmask16 而不是其他类型。我没有进行太多测试,但看起来 ICC 不介意采用不正确的类型,但如果您使用内在函数,GCC 似乎确实会尝试确保掩码中只有 16 位。
我没有查看上述说明的正确内在函数以及其他 __mmask* 类型变体,还是有其他方法可以在不诉诸内联汇编的情况下实现相同的目标?
【问题讨论】:
-
请注意,屏蔽指令只能在 Skylake-avx512 的一个 ALU 端口上运行。我不确定哪个端口,但它是与向量指令冲突的端口之一。 (
kmov到/从整数寄存器可能也使用该端口,因此移动到整数并返回单个移位对于吞吐量来说仍然是愚蠢的,如果不是延迟的话)。 -
至少对于
ktest/jcc,移动到整数寄存器而不是使用ktest允许将test/jcc与-march=skylake-AVX512进行宏融合。对-march=knl来说简直是愚蠢。 -
出于兴趣,为了需要额外的 KMOV,实现融合是否值得?也就是说,
ktest+jcc与kmov+test/jcc? -
这可能至少在前端问题吞吐量方面达到收支平衡,但对于代码大小来说更糟。
ktest+jcc是 2 或 3 微秒。希望ktest只是 1,但 SSE/AVXptest是 2 uop(1 用于测试,1 用于将结果从向量域移动到整数,与movd相同的端口)。kmov+test/jcc几乎可以肯定总共只有 2 个微指令。
标签: c gcc intrinsics icc avx512