在对Faiss CPU profiling分析时对libfaiss.o进行反汇编发现该程序没有用到avx512指令进行优化,而该指令在进行浮点运算时相比其他指令集会有更好的效率和速度,故在此记录将AVX512指令集添加进程序的编译过程。
openblas 是一个开源的矩阵计算库,包含了诸多的精度和形式的矩阵计算算法。就精度而言,包括float和double,两种数据类型的数据,其矩阵调用函数也是不一样。不同矩阵,其计算方式也是有所不同,(姑且认为向量也是一维矩阵),例如,向量与向量之间的计算,向量与矩阵之间的计算,矩阵与矩阵之间的计算。
Faiss在编译时就要用到这个库,所以在编译这个库时需要支持AVX512。
根据CPU架构的不同,OpenBLAS支持多种不同指令集,它判断当前CPU架构的步骤如下:
OpenBLAS支持使用GCC和clang两种编译器,对GCC的版本要求是大于gcc-6,clang的要求是大于clang-5。否则编译器不支持AVX512指令。
如getarch.c
#if (( defined(__GNUC__) && __GNUC__ > 6 && defined(__AVX2__)) || (defined(__clang__) && __clang_major__ >= 6))
#else
#define NO_AVX512
#endif
通过上述信息可以判断出CPU属于哪一系列,如我使用的vendor=1, family=6, exfamily=0, model=5, exmodel=5。
cpuid_x86.c/get_cpuname()
family = get_cputype(GET_FAMILY);
exfamily = get_cputype(GET_EXFAMILY);
model = get_cputype(GET_MODEL);
exmodel = get_cputype(GET_EXMODEL);
vendor = get_vendor();
cpuid_x86.c
int support_avx512(){
#if !defined(NO_AVX) && !defined(NO_AVX512)
int eax, ebx, ecx, edx;
int ret=0;
if (!support_avx())
return 0;
cpuid(7, &eax, &ebx, &ecx, &edx);
if((ebx & 32) != 32){
ret=0; //OS does not even support AVX2
}
if((ebx & (1<<31)) != 0){
xgetbv(0, &eax, &edx);
if((eax & 0xe0) == 0xe0)
ret=1; //OS supports AVX512VL
}
return ret;
#else
return 0;
#endif
}
由于我用的Ubuntu16.04 使用的GCC版本是5.4.0版本,所以OpenBLAS认为CPU不支持AVX512指令,编译出来的库文件为libopenblas_haswellp-r0.3.8.dev.so,如下图所示:
# 安装gcc-7
sudo apt-get install gcc-7, g++-7
# 安装gfortran-7
sudo apt-get install gfortran-7
# 修改默认属性
cd /usr/bin
rm -f gcc, g++, gfortran
ln -s gcc-7 gcc
ln -s g++-7 g++
ln -s gfortran-7 gfortran
make clean
make FC=gfortran
make install
操作完成后会将生成的库文件添加进/opt/OpenBLAS/lib目录中。如下图所示:
vim makefile.inc
CPUFLAGS = -mpopcnt -msse4
# 修改为
CPUFLAGS = -mpopcnt -msse4 -mavx512f -mavx512cd
make clean
make -j32
make install
objdump -S libfaiss.o > objdump_libfaiss.txt
返汇编代码可以看到包含诸如vmovss等AVX512指令: