我有一个在支持AVX-512的Intel机器上运行的进程,但是这个进程不直接使用任何AVX-512指令(asm或内在函数)并且编译时-mno-avx512f使编译器不插入任何AVX-512指令.
然而,它在减少的AVX turbo频率下无限运行.毫无疑问,有一个AVX-512指令在某个地方偷偷摸摸,通过一个库,(非常不可能)系统调用或类似的东西.
而不是尝试"二进制搜索"AVX-512指令来自哪里,有没有什么方法可以立即找到它,例如,捕获这样的指令?
操作系统是Ubuntu 16.04.
我理解VZEROUPPER在混合SSE和AVX代码时使用很重要,但如果我只使用AVX(和普通的x86-64代码)而不使用任何传统的SSE指令呢?
如果我从不在我的代码中使用单个SSE指令,是否有任何性能原因我需要使用VZEROUPPER?
这假设我没有调用任何外部库(可能使用SSE).
我们的64位应用程序有很多代码(特别是在标准库中),它们在SSE模式下使用xmm0-xmm7寄存器.
我想使用ymm寄存器实现快速内存复制.我无法修改使用xmm寄存器添加VEX前缀的所有代码,我也认为这是不实际的,因为它会增加代码的大小,因为需要CPU解码更大的指令会使它运行得更慢.
我只是想使用两个ymm寄存器(可能是zmm - 支持zmm的经济型处理器可以在今年推出)用于快速内存复制.
问题是:如何使用ymm寄存器但避免过渡处罚?
当我使用ymm8-ymm15寄存器(不是ymm0-ymm7)时会发生惩罚吗?SSE最初有8个128位寄存器(xmm0-xmm7),但在64位模式下,(xmm8-xmm15)也可用于非VEX前缀指令.但是,我已经审查了我们的64位应用程序,它只使用xmm0-xmm7,因为它也有一个32位版本,几乎相同的代码.仅当CPU尝试使用之前使用过的xmm寄存器为ymm并且具有高128位非零值时才会发生惩罚吗?将快速内存复制后使用的ymm寄存器归零是不是更好?例如,我曾使用ymm寄存器复制32个字节的内存 - 将它归零的最快方法是什么?"vpxor ymm15,ymm15,ymm15"足够快吗?(AFAIK,vpxor可以在3个ALU执行端口中的任何一个上执行,p0/p1/p5,而vxorpd只能在p5上执行).是不是将它归零的时间超过使用它来复制32字节内存的收益?
这是我在 AVX512BW 中的“strlen”函数的代码
vxorps zmm0, zmm0, zmm0 ; ZMM0 = 0
vpcmpeqb k0, zmm0, [ebx] ; ebx is string and it's aligned at 64-byte boundary
kortestq k0, k0 ; 0x00 found ?
jnz .chk_0x00
Run Code Online (Sandbox Code Playgroud)
现在对于'chk_0x00',在x86_64系统中,没有问题,我们可以这样处理:
chk_0x00:
kmovq rbx, k0
tzcnt rbx, rbx
add rax, rbx
Run Code Online (Sandbox Code Playgroud)
这里我们有一个 64 位寄存器,因此我们可以将掩码存储到其中,但我的问题是关于 x86 系统,我们没有任何 64 位寄存器,因此我们必须使用“内存”保留(8 字节)并检查两者掩码的DWORD一一对应(其实这是我的方式,我想知道有没有更好的方式)
chk_0x00:
kmovd ebx, k0 ; move the first dword of the mask to the ebx
test ebx, ebx ; 0x00 found in the first dword ?
jz …Run Code Online (Sandbox Code Playgroud) 在英特尔内部函数指南,vmulpd并vfmadd213pd已延迟5,vaddpd具有延迟3。
我写了一些测试代码,但所有的结果都慢了 1 个周期。
这是我的测试代码:
.CODE
test_latency PROC
vxorpd ymm0, ymm0, ymm0
vxorpd ymm1, ymm1, ymm1
loop_start:
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
sub rcx, 4
jg loop_start
ret
test_latency ENDP
END
Run Code Online (Sandbox Code Playgroud)
.CODE
test_latency PROC
vxorpd ymm0, ymm0, ymm0
vxorpd ymm1, ymm1, ymm1
loop_start:
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
vmulpd ymm0, ymm0, ymm1
sub rcx, 4
jg …Run Code Online (Sandbox Code Playgroud) 在某些 Intel 处理器上混合使用和不使用 AVX 支持编译的代码时会出现问题。由于 YMM 寄存器状态的变化,从 AVX 代码到非 AVX 代码会导致性能下降。在从 AVX 代码到非 AVX 代码的任何转换之前,应该通过调用内部函数 _mm256_zeroupper() 来避免这种惩罚。在以下情况下,这可能是必要的:
• 如果程序的一部分是使用 AVX 支持编译的,而程序的另一部分是在没有 AVX 支持的情况下编译的,则在离开 AVX 部分之前调用 _mm256_zeroupper()。
• 如果使用 CPU 调度在使用和不使用 AVX 的多个版本中编译函数,则在离开 AVX 部分之前调用 _mm256_zeroupper()。
• 如果一段使用AVX 支持编译的代码调用了编译器自带的库以外的库中的函数,而该库没有AVX 支持,则在调用库函数之前先调用_mm256_zeroupper()。
我想知道什么是英特尔处理器。具体来说,是否有过去五年制造的处理器。这样我就知道修复丢失的_mm256_zeroupper()电话是否为时已晚。
x86 ×5
avx ×4
assembly ×3
avx512 ×3
intel ×3
performance ×3
sse ×2
32-bit ×1
c++ ×1
intrinsics ×1
linux ×1
optimization ×1
simd ×1
x86-64 ×1