avx2支持需通过cpuid叶子节点0x00000007的ebx[5]位判断:windows调用__cpuid(cpuinfo, 0x00000007)后检查cpuinfo[1]第5位,linux/macos用__get_cpuid(7, &eax, &ebx, &ecx, &edx)后检查ebx&(1

用__cpuid查0x00000007叶子节点的EBX[5]
AVX2 支持必须通过 CPUID 叶子节点 0x00000007 检查,不能只看 EAX=1 的结果。Windows 下调用 __cpuid(cpuInfo, 0x00000007) 后,cpuInfo[1](即 EBX)第 5 位为 1 表示硬件支持 AVX2。
Linux/macOS 下用 __get_cpuid(7, &eax, &ebx, &ecx, &edx),同样检查 ebx & (1 。
注意前置条件:必须先调一次 __cpuid(cpuInfo, 0) 确认 CPUID 指令本身可用——否则在极老 CPU(如 Pentium Pro 之前)上会触发 #UD 异常。
__builtin_cpu_supports("avx2") 是最简方案,但有编译器限制
GCC ≥ 4.9 / Clang ≥ 3.5 支持该内建函数,直接传字符串字面量 "avx2",返回非零即表示当前 CPU 支持。
它内部已封装好 CPUID 调用和 OS 状态检查(比如 XGETBV),比手写更安全;但要求字符串必须是编译期常量,不能拼接或来自变量。
常见错误:const char* s = "avx2"; if (__builtin_cpu_supports(s)) —— 这会编译失败,因为不是字面量。
别漏掉 OS 层级的 AVX 支持检查
即使 CPU 支持 AVX2,若操作系统没启用 XSAVE/XRSTOR(例如某些嵌入式 Linux 或虚拟机未配置),执行 AVX2 指令仍会触发 #UD 异常。
Windows 下需额外调用 xgetbv(0) 并验证低两位是否为 0b11;Linux 下推荐用 getauxval(AT_HWCAP) 配合 HWCAP_AVX2 标志,它由内核在启动时确认过 OS 支持状态。
仅靠 __cpuid 查到 EBX[5] == 1 不足以保证能安全执行——这是最容易被跳过的一步。
__AVX2__ 宏完全不可信,别拿它做运行时判断
__AVX2__ 是纯编译期宏,由 -mavx2 触发,只说明“这段代码被编译成含 AVX2 指令”,和目标机器毫无关系。
典型翻车:#ifdef __AVX2__ run_avx2_code(); #else run_fallback(); #endif —— 这在预处理阶段就决定了分支,根本不会运行时检测 CPU。
更危险的是:if (__AVX2__) { ... },此时 __AVX2__ 是整数常量(值为 1),条件恒真,等价于裸写代码,毫无保护作用。
AVX2 检测真正的难点不在读哪个寄存器位,而在于把「CPU 硬件支持」+「OS 上下文管理就绪」+「当前进程可访问」三者串成一条完整链路;少一环,_mm256_i32gather_epi32 就可能让程序当场退出。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











