如何验证Eigen3是否生成AVX2或AVX512F指令代码?
Eigen3 + AVX/AVX2/AVX-512F 向量化验证与优化实践
问题背景
我正在开发一款涉及大量低延迟硬实时矩阵运算的程序,采用Eigen3库实现。目标是在生产环境中通过AVX-512F SIMD向量化技术提升性能。当前在Ubuntu系统上实验,通过vcpkg安装Eigen3,本机支持AVX2,后续将通过BIOS开启AVX-512F。
初始验证情况
我用以下命令分析目标文件的寄存器使用:
objdump -d main.o | grep zmm objdump -d main.o | grep ymm objdump -d main.o | grep xmm
结果zmm和ymm相关指令无输出,仅xmm能查到寄存器操作,示例片段如下:
3d84: 0f 28 08 movaps (%rax),%xmm1 3d87: 0f 29 4d d0 movaps %xmm1,-0x30(%rbp) 3d8b: 0f 29 45 e0 movaps %xmm0,-0x20(%rbp) 3d8f: 0f 28 45 d0 movaps -0x30(%rbp),%xmm0 3d93: 0f 12 45 e8 movlps -0x18(%rbp),%xmm0 3d9f: 0f 28 08 movaps (%rax),%xmm1 3da2: 0f 29 4d b0 movaps %xmm1,-0x50(%rbp) 3da6: 0f 29 45 c0 movaps %xmm0,-0x40(%rbp) 3daa: 0f 28 45 b0 movaps -0x50(%rbp),%xmm0 3dae: 0f 58 45 c0 addps -0x40(%rbp),%xmm0 3db2: 0f 29 45 80 movaps %xmm0,-0x80(%rbp) 3db6: 0f 28 45 80 movaps -0x80(%rbp),%xmm0 3dba: 0f 28 4d 80 movaps -0x80(%rbp),%xmm1 3dbe: 0f c6 c1 01 shufps $0x1,%xmm1,%xmm0
我需要确认:
- 当前g++是否为Eigen3生成了AVX1(128位)代码?
- 如何验证是否生成了正确的AVX2或AVX-512F SIMD代码?
更新内容:测试代码与编译命令
测试代码
#include <eigen3/Eigen/Core> #include <eigen3/Eigen/Dense> using namespace Eigen; int main() { // Matrix4f a, b, cadd, cmul, ci, ct, d; // a = Matrix4f::Random(); // b = Matrix4f::Random(); MatrixXf a(100, 100),b(100, 100),cadd(100, 100), cmul(100, 100), ci(100, 100), ct(100, 100); a = MatrixXf::Random(100, 100); b = MatrixXf::Random(100, 100); cadd = a + b; cmul = a * b; ci = cadd.inverse(); ct = cadd.transpose(); }
初始编译命令
g++ -Wall -fexceptions -I/home/user/vcpkg/installed/x64-linux/include -c /home/user/Desktop/VectorClass/main.cpp -o obj/Debug/main.o g++ -L/home/user/vcpkg/installed/x64-linux/debug/lib -o bin/Debug/VectorClass obj/Debug/main.o -mavx2 -mtune=native -host=native -march=native
最终验证结果与优化编译命令
反汇编输出
objdump -d main.o | grep ymm结果:
14f: c5 fe 7f 45 98 vmovdqu %ymm0,-0x68(%rbp) 231: c5 fd 7f 85 50 fe ff vmovdqa %ymm0,-0x1b0(%rbp)
objdump -d main.o | grep zmm结果:
a1: 62 f1 7c 48 28 74 24 vmovaps 0x80(%rsp),%zmm6 ac: 62 f1 4c 48 58 44 24 vaddps 0x40(%rsp),%zmm6,%zmm0 b4: 62 f1 7c 48 29 44 24 vmovaps %zmm0,0xc0(%rsp) 228: 62 f1 7c 48 28 7c 24 vmovaps 0x180(%rsp),%zmm7 230: 62 f1 7c 48 29 7c 24 vmovaps %zmm7,0x100(%rsp) 2d0: 62 f1 7d 48 6f 05 00 vmovdqa32 0x0(%rip),%zmm0 # 2da <main+0x2da> 2dd: 62 f2 7d 48 16 44 24 vpermps 0xc0(%rsp),%zmm0,%zmm0 2e5: 62 f1 7c 48 29 44 24 vmovaps %zmm0,0x180(%rsp)
对应的优化编译命令
g++ -Wall -fexceptions -I/home/user/vcpkg/installed/x64-linux/include -c main.cpp -o main.out -mavx512f -mfma -mtune=native -host=native -march=native -mprefer-vector-width=512 -O3 -fno-math-errno -ffinite-math-only -fno-rounding-math -funsafe-math-optimizations
问题解答
初始xmm指令的归属
你看到的movaps、addps等是SSE指令,不属于AVX1。AVX1的指令会带V前缀(如vmovaps),且使用ymm寄存器。当时没生成AVX/AVX2代码的核心原因:
- 编译阶段(
-c步骤)未开启优化等级(默认-O0),Eigen的向量化优化需要至少-O2才能激活; - 初始编译命令中
-mavx2等SIMD参数仅加在链接阶段,编译目标文件时未生效,导致编译器未启用AVX2指令集。
验证AVX2/AVX-512F代码生成的方法
- 识别指令特征
- AVX2指令:以
V开头,使用ymm寄存器(例如vmovdqu、vmovdqa),机器码前缀为C5/C4; - AVX-512F指令:机器码以
62开头,使用zmm寄存器(例如vmovaps、vaddps搭配zmm);
- AVX2指令:以
- 正确配置编译参数
- 必须在编译阶段(
-c步骤)添加指令集参数:-mavx2(AVX2)或-mavx512f(AVX-512F); - 开启优化等级
-O3,配合-mprefer-vector-width=512强制优先使用512位向量; - 添加
-funsafe-math-optimizations、-ffinite-math-only等参数,让Eigen能最大化利用SIMD进行矩阵运算优化;
- 必须在编译阶段(
- 反汇编验证
- 用
objdump -d main.o | grep ymm检查AVX2指令; - 用
objdump -d main.o | grep zmm检查AVX-512F指令; - 也可以用
objdump -d main.o | grep -E 'vmov|vadd|vperm'过滤AVX系列指令。
- 用
内容的提问来源于stack exchange,提问作者Dark Sorrow
相关产品推荐
相关产品推荐

