X86 苏格兰和南方能源公司、AVX公司是否有遗漏?

X86 苏格兰和南方能源公司、AVX公司是否有遗漏?,x86,sse,simd,avx,X86,Sse,Simd,Avx,这是我的想象,还是SSE和AVX缺少一条PNOT指令?也就是说,翻转向量中每一位的指令 如果是,有没有比矢量为1的px或px更好的模拟方法?非常烦人,因为我需要设置一个所有1的向量来使用这种方法。如果使用intrinsic,可以使用这样的内联函数来分别执行not操作 inline uuum256i mm256 uui256(uuum256i a){ //返回_mm256_xor_si256(a,_mm256_set1_epi32(0xffffffff)); return _mm256_xor_s

这是我的想象,还是SSE和AVX缺少一条
PNOT
指令?也就是说,翻转向量中每一位的指令


如果是,有没有比矢量为1的px或px更好的模拟方法?非常烦人,因为我需要设置一个所有1的向量来使用这种方法。

如果使用intrinsic,可以使用这样的内联函数来分别执行not操作

inline uuum256i mm256 uui256(uuum256i a){
//返回_mm256_xor_si256(a,_mm256_set1_epi32(0xffffffff));
return _mm256_xor_si256(a,_mm256_cmpeq_epi32(a,a));//我没有检查哪个更快
}

对于这种情况,了解编译器将生成什么内容会很有帮助

例如,对于以下功能:

#包括
__m256i测试(常数m256i v)
{
返回~v;
}
gcc和clang似乎都:

您可以使用操作码来实现这一点

PANDN
执行该操作

DEST = NOT(DEST) AND SRC   ; (SSEx)

将此操作与all ones向量有效地结合在一起将导致PNOT操作


某些x86(SSEx)汇编代码如下所示:

; XMM0 is input register
PCMPEQB   xmm1, xmm1        ; Whole xmm1 reg set to 1's
PANDN     xmm0, xmm1        ; xmm0 = NOT(xmm0) AND xmm1
; XMM0 contains NOT(XMM0)
; YMM0 is input register
VPCMPEQB  ymm1, ymm1, ymm1  ; Whole ymm1 reg set to 1's
VPANDN    ymm0, ymm0, ymm1  ; ymm0 = NOT(ymm0) AND ymm1
; YMM0 contains NOT(YMM0)
某些x86(AVXx)汇编代码如下所示:

; XMM0 is input register
PCMPEQB   xmm1, xmm1        ; Whole xmm1 reg set to 1's
PANDN     xmm0, xmm1        ; xmm0 = NOT(xmm0) AND xmm1
; XMM0 contains NOT(XMM0)
; YMM0 is input register
VPCMPEQB  ymm1, ymm1, ymm1  ; Whole ymm1 reg set to 1's
VPANDN    ymm0, ymm0, ymm1  ; ymm0 = NOT(ymm0) AND ymm1
; YMM0 contains NOT(YMM0)
当然,两者都可以很容易地转换为内部函数。

AVX512F/最终提供了一种实现方法,它使用一条指令,可以在Skylake-avx512上的任何向量ALU端口上运行

使用AVX512VL,也可用于128和256位向量,而不会弄脏ZMM的上部。(除Xeon Phi外,所有AVX512 CPU均具有AVX512VL)

在Skylake-X上,当在展开循环中仅运行此指令时,某些神秘的效果将吞吐量限制在~0.48/时钟,即使128和256位向量也是如此,即使有6到10个独立的依赖链,即使它可以在p015中的任何一个上运行。Ice Lake达到了预期的3/时钟吞吐量。()

ZMM版本在任何地方运行2/时钟,端口1 SIMD ALU关闭 在SKX/ICL上,因为512位UOP正在运行


vpternlogd zmm、zmm、zmm、imm8
有3个输入向量和一个输出,修改了目标位置。有了正确的立即数,您仍然可以实现一个拷贝,而不是到另一个寄存器中,但是它将对输出寄存器有一个“false”依赖关系(这不会)

TL:DR:可能仍然将异或与所有的异或作为循环的一部分使用,除非寄存器用完了<如果以后需要输入,code>vpternlog可能需要额外的
vmovdqa
寄存器复制指令。

在循环之外,
vpternlogd zmm,zmm,zmm,0xff
是,因为AVX512将指令比较成掩码(
k0-k7
),所以对于512位向量,与所有指令的异或可能已经涉及
vpternlogd
,或者来自内存的广播常数。或用于128或256位
vpcmpeqd的dep中断ALU uop相同,相同



对于每个位位置
i
,输出位是
imm[(DEST[i]设置所有
1
s的向量并不特别困难:
[v]pcmpe[typesize][x/y]mmN、%[x/y]mmN[,%[x/y]mmN]
或其他。设置常数的单个指令似乎不太繁重。如果您特别讨厌
xor
pandn
以及NPS
也可以使用。这并不可怕-但它是我期望的基本操作的2倍长。当然,常数可以在e寄存器的费用。无论如何,只要检查一下我的假设,我没有遗漏它。@EOFI大体上同意。这对我来说很重要。我的吞吐量和端口限制在3个向量端口上。每个向量操作花费我1/3个周期(在合理范围内)。@EOF这里有一个
和NPD
(而不是)在SSE中。类似地:
PNEG
指令在哪里?谢谢Paul。这是一个很好的指示,我想没有更好的了。s/indication/indication/good编译器通常会优化
\u mm256\u set1\u epi32(-1)
到一个
vpcmpeqd相同,相同的
。我想对于AVX来说,如果它不正常的话,尝试“欺骗”它发出这种信号可能不会伤害编译器。(对于SSE,它可能需要额外的MOVDQA指令,但AVX 3操作数编码解决了这个问题。)我不同意“它没有PXOR那么好”第2部分ops/cycle是Skylake上AVX512命令的最大可能吞吐量,PADD b PAND组中只有少数命令达到此速度。2*512>3*256,因此在这些命令上,AVX512仍比其他命令快33%AVX2@Bulat:我不是这么说的。它不太好,因为它不能复制,而且对输出注册表没有错误的依赖关系呃,因此您的编译器可能会在
vmovdqa32
上浪费一些前端吞吐量。此外,128位和256位版本的AVX512VL指令通常是3/时钟,包括
vpternlogd ymm
。如果您只使用256位向量来避免整个程序中的某一小部分出现turbo惩罚,您仍然可以使用
vpternlogd ymm
。此外,FP-FMA/add/mul是2/clock on Gold,因此IDK您所说的“只有少数”指令以2/clock的速度运行512位向量。
vpternlogd  zmm1,zmm1, zmm2,  01010101b  ; 0x55  ; false dep on zmm1
// To hand-hold a compiler into saving a vmovdqa32 if needed:
__m512i tmp = something earlier;
__m512i t2 = _mm...(tmp);
// use-case: tmp is dead, t2 and ~t2 are both needed.
__m512i t2_inv = _mm512_ternarylogic_epi32(tmp, t2, t2, 0b01010101);
__m512i t2_inv = _mm512_ternarylogic_epi32(t2, t2, t2, 0b01010101);