Eigen框架启用AVX512编译时整数矩阵乘法性能异常下降的原因排查问询
Eigen框架启用AVX512编译时整数矩阵乘法性能异常下降的原因排查问询
我最近在测试无符号32位整数矩阵乘法的性能,结果发现了一个非常反常的现象:当用AVX512指令集编译Eigen的无符号32位整数矩阵乘法时,性能会出现大幅下降,而浮点数矩阵乘法的性能在AVX2和AVX512编译下基本一致。下面是我的完整测试过程和发现,想请教社区的大佬们这可能是什么原因导致的?
问题发现与多环境验证
初始异常
一开始我以为整数矩阵乘法比浮点数慢是正常情况,但没想到Eigen优化后的u32矩阵乘法,居然比自己写的5行naive实现还慢3-5倍。进一步调整编译选项后,我发现了更关键的差异:
- 用
-march=skylake(仅启用AVX2、FMA)编译时,Eigen的u32矩阵乘性能符合预期; - 用AVX512相关参数编译时,Eigen的u32矩阵乘性能暴跌,而浮点数矩阵乘的速度在两种编译选项下几乎没有差异。
多环境测试排除干扰
我先后在多个环境中验证,排除了硬件和虚拟机的影响:
- VM中的i5-11400F:AVX2编译的Eigen u32乘比AVX512快很多,浮点乘无差异,最初以为是VM配置问题,但换物理机后问题仍存在;
- 物理机i5-11400F:AVX2编译的Eigen u32乘性能回归正常,但AVX512编译下的u32乘依然远慢于AVX2;
- AMD Ryzen 9 9950X(支持AVX512):同样出现AVX512编译下Eigen u32矩阵乘性能大幅下降的问题,浮点乘性能无明显差异。
测试环境明细
- CPU型号:Intel i5-11400F(VM/物理机)、AMD Ryzen 9 9950X
- 操作系统:Ubuntu 20.04
- 编译器:g++ 13.3
- Eigen版本:5.0.0(代码中显示为3.5.0)
- OpenBLAS版本:0.3.8(编译配置:NO_LAPACKE、DYNAMIC_ARCH、NO_AFFINITY、USE_OPENMP;运行核心:Prescott)
依赖安装命令
sudo apt update && sudo apt install -y software-properties-common sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt update sudo apt install -y gcc-13 g++-13 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 130 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 130 sudo update-alternatives --install /usr/bin/cpp cpp /usr/bin/cpp-13 130 # 安装Eigen 5.0.0 sudo apt install -y build-essential cmake git git clone --depth=1 --branch 5.0.0 https://gitlab.com/libeigen/eigen.git cmake -S eigen -B build -DCMAKE_BUILD_TYPE=Release -DEIGEN_BUILD_TESTING=OFF sudo cmake --install build sudo apt install -y libopenblas-openmp-dev
编译与运行命令
编译命令
AVX2版本(-march=skylake)
g++ -std=c++17 -O3 bench_eigen.cpp -march=skylake -mavx2 -mfma -I/usr/local/include/eigen3 -DEIGEN_USE_BLAS -DNDEBUG -DEIGEN_DONT_PARALLELIZE -o bench_eigen -lopenblas -ldl -lpthread
AVX512版本
g++ -std=c++17 -O3 bench_eigen.cpp -march=native -mavx512f -mavx512vl -mavx512bw -mavx512dq -mavx2 -mfma -I/usr/local/include/eigen3 -DEIGEN_USE_BLAS -DNDEBUG -DEIGEN_DONT_PARALLELIZE -o bench_eigen -lopenblas -ldl -lpthread
运行命令(强制单线程)
为排除多线程干扰,我用以下命令强制单线程运行:
OMP_NUM_THREADS=1 \ OPENBLAS_NUM_THREADS=1 \ MKL_NUM_THREADS=1 \ BLIS_NUM_THREADS=1 \ VECLIB_MAXIMUM_THREADS=1 \ NUMEXPR_MAX_THREADS=1 \ TBB_NUM_THREADS=1 \ taskset -c 0 ./bench_eigen
具体测试结果
所有结果耗时单位为毫秒,测试矩阵为M×M:
A (naive u32):手动实现的naive无符号32位整数矩阵乘法E (Eigen u32):Eigen优化的无符号32位整数矩阵乘法F (Eigen float):Eigen的32位浮点数矩阵乘法
1. AVX2编译结果
| 测试环境 | 矩阵大小M | A (naive u32) | E (Eigen u32) | F (Eigen float) |
|---|---|---|---|---|
| i5-11400F(VM) | 128 | 0.195786 | 0.230665 | 0.343123 |
| i5-11400F(VM) | 256 | 2.53591 | 2.43643 | 2.55185 |
| i5-11400F(VM) | 512 | 21.0246 | 12.9793 | 10.7131 |
| i5-11400F(VM) | 1024 | 99.9402 | 60.1828 | 92.6357 |
| i5-11400F(VM) | 2048 | 1752.68 | 602.128 | 790.347 |
| i5-11400F(VM) | 4096 | 15556.7 | 4897.88 | 6155.12 |
| i5-11400F(VM) | 8192 | 125991 | 34135.3 | 46756.6 |
| i5-11400F(物理机) | 128 | 0.12163 | 0.116401 | 0.075121 |
| i5-11400F(物理机) | 256 | 1.09552 | 0.919345 | 0.371853 |
| i5-11400F(物理机) | 512 | 10.6812 | 6.0438 | 2.51853 |
| i5-11400F(物理机) | 1024 | 79.6962 | 46.3137 | 18.0736 |
| i5-11400F(物理机) | 2048 | 1042.06 | 369.876 | 135.139 |
| i5-11400F(物理机) | 4096 | 10479.9 | 2960.94 | 1050(原数据不全) |
| i5-11400F(物理机) | 8192 | 90380.7 | 23885.2 | 8307.87 |
2. AVX512编译结果
| 测试环境 | 矩阵大小M | A (naive u32) | E (Eigen u32) | F (Eigen float) |
|---|---|---|---|---|
| i5-11400F(VM) | 8192 | 106590 | 169307 | 45510.9 |
| i5-11400F(物理机) | 8192 | 90707.9 | 131440 | 8217.99 |
| AMD Ryzen 9 9950X | 8192 | 49783.9 | 78567 | 3616.15 |
关键结论
从所有测试结果中能明确看到:
- 无论Intel还是AMD CPU,AVX512编译的Eigen u32矩阵乘法耗时都远高于AVX2版本(比如物理机i5的8192大小矩阵,AVX512下Eigen u32耗时131440ms,AVX2下仅23885.2ms);
- 浮点数矩阵乘法在AVX2和AVX512编译下的性能基本持平,无明显差异;
- Naive实现的u32矩阵乘法在AVX2和AVX512编译下的性能差异不大。
想请教大家,这种Eigen整数矩阵乘法在AVX512编译下性能暴跌的情况,可能是编译器的优化逻辑问题?还是Eigen对AVX512整数矩阵乘法的支持存在bug?或者是OpenBLAS的适配问题?




