为256向量化寄存器编写的代码将使用使用O3优化级别的(2019)英特尔编译器编译为使用512条指令吗?
。对两个__m256d对象的操作是否会被转换为对掩码__m512d对象的相同数量的操作,或者分组以最大限度地利用寄存器,在最好的情况下,操作总数下降了2倍?
arch: Knights Landing
遗憾的是,没有:使用AVX/AVX-2 intrinsic编写的代码不会被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可以使您的代码速度提高一倍。