使用具有 O3 优化级别的 (2019) 英特尔编译器,为 256 个向量化寄存器编写的代码是否会被编译为使用 512 个指令?
例如对两个 __m256d 对象的操作是否会转换为对屏蔽 __m512d 对象的相同数量的操作,或者进行分组以充分利用寄存器,在最好的情况下,操作总数会下降 2 倍?
拱门:骑士登陆
最佳答案
不幸的是,否:为使用 AVX/AVX-2 内在函数而编写的代码未被 ICC 重写,因此尚未使用 AVX-512(ICC 2019 和 ICC 2021)。没有指令熔断。这是一个示例(请参阅 GodBolt )。
#include <x86intrin.h>
void compute(double* restrict data, int size)
{
__m256d cst1 = _mm256_set1_pd(23.42);
__m256d cst2 = _mm256_set1_pd(815.0);
__m256d v1 = _mm256_load_pd(data);
__m256d v2 = _mm256_load_pd(data+4);
__m256d v3 = _mm256_load_pd(data+8);
__m256d v4 = _mm256_load_pd(data+12);
v1 = _mm256_fmadd_pd(v1, cst1, cst2);
v2 = _mm256_fmadd_pd(v2, cst1, cst2);
v3 = _mm256_fmadd_pd(v3, cst1, cst2);
v4 = _mm256_fmadd_pd(v4, cst1, cst2);
_mm256_store_pd(data, v1);
_mm256_store_pd(data+4, v2);
_mm256_store_pd(data+8, v3);
_mm256_store_pd(data+12, v4);
}
生成的代码:
compute:
vmovupd ymm0, YMMWORD PTR .L_2il0floatpacket.0[rip] #5.20
vmovupd ymm1, YMMWORD PTR .L_2il0floatpacket.1[rip] #6.20
vmovupd ymm2, YMMWORD PTR [rdi] #7.33
vmovupd ymm3, YMMWORD PTR [32+rdi] #8.33
vmovupd ymm4, YMMWORD PTR [64+rdi] #9.33
vmovupd ymm5, YMMWORD PTR [96+rdi] #10.33
vfmadd213pd ymm2, ymm0, ymm1 #11.10
vfmadd213pd ymm3, ymm0, ymm1 #12.10
vfmadd213pd ymm4, ymm0, ymm1 #13.10
vfmadd213pd ymm5, ymm0, ymm1 #14.10
vmovupd YMMWORD PTR [rdi], ymm2 #15.21
vmovupd YMMWORD PTR [32+rdi], ymm3 #16.21
vmovupd YMMWORD PTR [64+rdi], ymm4 #17.21
vmovupd YMMWORD PTR [96+rdi], ymm5 #18.21
vzeroupper #19.1
ret #19.1
为两个版本的 ICC 生成相同的代码。
请注意,使用 AVX-512 并不总是能将代码速度提高两倍。例如,在 Skylake SP(服务器端处理器)上,有 2 个 AVX/AVX-2 SIMD 单元可以融合来执行 AVX-512 指令,但融合不会提高吞吐量(假设 SIMD 单元是瓶颈)。不过,Skylake SP 还支持可选额外的 512 位 SIMD 单元,该单元不支持 AVX/AVX-2(仅在某些处理器上可用)。在这种情况下,AVX-512 可以使您的代码速度提高一倍。
关于performance - intel -03会将成对的__m256d指令转换为__m512d,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72849916/