【大模型换机器部署失败原因排查】一次 `Illegal instruction` 排查:原来是虚拟机没暴露 AVX 指令集

​ 昨天在重新构建服务时,遇到了一个非常"底层"的问题。最开始看日志,还以为是业务代码、依赖或者容器环境的问题,结果一路排查下去,最后发现问题根本不在 Python,而在虚拟机 CPU 指令集。

​ 这篇文章就完整记录一下这次排查过程。

一、问题描述

1.1 部署失败

​ 重新构建后,其中一个节点启动失败。日志如下:

bash 复制代码
+ python main.py log.yml 5000

/usr/local/lib/python3.10/site-packages/polars/_cpu_check.py:259: RuntimeWarning: Missing required CPU features.

The following required CPU features were not detected:
    avx, avx2, fma, bmi1, bmi2, lzcnt, pclmulqdq, movbe

Continuing to use this version of Polars on this processor will likely result in a crash.

Install the `polars-lts-cpu` package instead of `polars` to run Polars with better compatibility.

./web_entrypoint.sh: line 4: 39 Illegal instruction (core dumped) python main.py log.yml 5000

​ 可以看到其中的关键错误:

bash 复制代码
Illegal instruction (core dumped)

​ 以及:

bash 复制代码
Missing required CPU features:
avx, avx2, fma ...

1.2 排查第一步:是不是 polars 崩了?

​ 因为日志已经给了非常明显的提示:

bash 复制代码
Install the `polars-lts-cpu` package instead of `polars`

​ 因为 polars 默认会使用 AVX / AVX2 等现代 CPU 指令集优化 ,如果 CPU 不支持这些指令,在加载动态库时就可能直接触发:

bash 复制代码
SIGILL(Illegal Instruction)

​ 也就是说,Python 代码甚至还没真正开始执行,进程就已经被 CPU 杀掉了。

1.3 为什么只有一个节点出问题?

​ 这里有个关键现象:不是所有节点都失败,只有其中一个节点失败。

​ 这说明镜像本身没问题,requirements 没问题 ,代码没问题 ,只有某一台机器环境特殊。

​ 于是我开始怀疑是不是这个节点的 CPU 指令集不对?

二、检查 CPU 指令集

​ 先登录到失败的节点:

复制代码
ssh xxx@xxx.xxx.xxx.xxx

2.1 通过/proc/cpuinfo查看指令集

/proc/cpuinfo是 Linux 下的一个虚拟文件,可以使用cat查看:

bash 复制代码
cat /proc/cpuinfo

​ 里面包含CPU型号、核心数、cache、flags(支持的CPU指令集)。

​ 这里的flags非常重要,例如:

复制代码
flags : fpu vme de pse tsc ... avx avx2 fma bmi1 bmi2

​ 因为很多深度学习框架:PyTorch、TensorFlow、ONNX Runtime 、llama.cpp 、vLLM都会检测这些 CPU 指令集。

2.2 通过正则提取目标指令集

​ 从 Linux 的 CPU 信息中,提取当前 CPU 支持的一些关键指令集特性(如 AVX、FMA 等),并去重输出。主要用于检查 CPU 是否支持 AVX:

bash 复制代码
grep -m1 -oE 'avx[0-9]*|fma|bmi[0-9]*|lzcnt|pclmulqdq|movbe' /proc/cpuinfo | sort -u

​ 正常情况下应该看到:

bash 复制代码
avx
avx2
fma
bmi1
bmi2
...

​ 结果我运行后得到了一个空输出,这就非常异常了。

三、继续排查:CPU 型号是什么?

​ 通过model name查看当前系统识别的CPU型号信息:

bash 复制代码
grep -m1 "model name" /proc/cpuinfo

3.1 正常输出

​ 正常情况下,如果是在物理机器上,通常会看到类似:

bash 复制代码
model name      : Intel(R) Xeon(R) Gold 6230R CPU @ 2.10GHz
字段 含义
Intel® Intel 处理器
Xeon Intel 服务器级 CPU 产品线
Gold Xeon 的中高端等级
6230R 具体型号
2.10GHz 基础主频

3.2 问题输出

复制代码
QEMU Virtual CPU version 2.5+

​ 说明当前环境并不是真实物理 CPU,而是运行在 QEMU 虚拟化环境中。

(1) QEMU是什么

​ QEMU 是一个开源的虚拟机 、硬件模拟器 、CPU 模拟器。

​ 它可以模拟不同 CPU 架构、创建虚拟机、提供隔离运行环境。

​ 很多场景都会使用 QEMU: 云服务器、Docker底层虚拟化、KVM、CI/CD环境、模型沙箱、安全隔离环境。

​ 这张图用堆叠的方式呈现了从硬件到应用的四层抽象:底层物理 CPU 是唯一真实的算力来源,QEMU/KVM 在其上构造出"假装是CPU"的虚拟硬件,Linux 虚拟机把这套假硬件当真硬件来跑内核,最上层你的程序则完全感知不到自己其实活在第三层之上。层与层之间的箭头方向也提示了一个关键事实,上层的每条指令最终都要落到最底层的物理 CPU 上执行。

四、问题根源:QEMU 使用了通用 CPU 模型

​ 通过上述CPU型号的输出说明当前虚拟机并没有直接暴露宿主机 CPU。而是使用了qemu64

​ 这种模式的特点是兼容性高、迁移方便、但会屏蔽 AVX / AVX2 等高级指令集。

​ 因此,即使物理机实际上支持 AVX,虚拟机里也完全看不到。

4.1 为什么会突然这样?

​ 后来同事提到这台机器之前做过一次迁移,这就完全对上了。

​ 因为很多虚拟化平台在 VM 迁移时,会默认把 CPU 模型降级成qemu64,目的就是保证 VM 可以迁移到不同 CPU 型号的宿主机上。

​ 代价则是AVX / AVX2 / FMA 等高级指令全部被隐藏。

4.2 为什么 polars 会直接崩?

​ 因为 polars 的默认构建会开启 AVX 优化,动态库内部直接使用 AVX 指令。而当前 VM根本不支持 AVX,于是 CPU 在执行指令时直接触发:

复制代码
SIGILL
Illegal instruction

​ 进程被系统杀掉。

五、解决方案---修改虚拟机 CPU 模式(推荐)

这是根治方案。

5.1 KVM / libvirt

​ 修改 VM 配置:

复制代码
<cpu mode='host-passthrough' check='none'/>

​ 或者:

复制代码
<cpu mode='host-model'/>

​ 让 VM 直接透传宿主机 CPU 指令集。

5.2 QEMU

​ 启动参数改成:

复制代码
-cpu host

​ 而不是:

复制代码
-cpu qemu64

5.3 修改后一定要:

复制代码
power-cycle(关机再开)

​ 不能只是 reboot,因为 CPU 特性是在 VM 启动时协商的。

六、这类问题为什么容易误判?

​ 因为表面现象非常像:Python 崩溃 /Docker 问题/依赖问题/C 扩展问题 。但实际上是 CPU 指令集问题。

​ 尤其是Illegal instruction这个错误。很多人第一反应是代码有 bug。实际上确是CPU 不认识这个指令。

七、以后再遇到 Illegal instruction 怎么排查?

7.1 Step1:先确认 CPU 支持哪些指令集

​ 第一件事,不是重装环境。而是先确认当前机器到底有没有 AVX / AVX2 / FMA?

复制代码
cat /proc/cpuinfo

​ 或者:

复制代码
lscpu

​ 重点看flags部分,例如:

bash 复制代码
flags : ... sse4_2 avx avx2 fma ...

​ 这里 avxavx2fma 代表 CPU 支持对应 SIMD 指令。

​ 如果没有avx但你的程序用了 AVX 指令,那么一定会发生这个问题。

7.2 Step2:确认是不是运行在虚拟机里

​ 有时候物理机支持 AVX2,但虚拟机不支持。

​ 继续查看:

复制代码
grep -m1 "model name" /proc/cpuinfo

​ 如果看到:

复制代码
QEMU Virtual CPU

​ 或者:

复制代码
Common KVM processor
Virtual CPU

​ 基本说明你运行在虚拟化环境中。

​ 这里要开始思考一个关键问题:虚拟机暴露的CPU kennel不是宿主机真实的CPU。也就是说宿主机可能是 Xeon Gold,但 VM 里看到的是"精简版 CPU" 。

​ 虚拟化平台为了做热迁移、保证兼容、统一集群,通常不会把全部 CPU 指令暴露给 Guest。于是就会出现这个问题,这也是很多线上问题最容易忽略的一点。

7.3 Step3:思考"是不是迁移导致的"

​ 如果以前能跑、迁移后跑不动,或者换了节点之后偶发失败,第一反应应该是怀疑 CPU model 被悄悄降级了。

复制代码
很多虚拟化平台和云厂商,为了让虚拟机能在不同物理机之间自由迁移,会统一各台宿主机暴露给 VM 的 CPU能力取交集,砍掉高级指令集。          
  • 举个最常见的场景:
    • Host A: AVX2 + FMA

    • Host B: 仅 AVX

      为了让虚拟机能在 A、B 之间随便漂移,平台干脆只对 VM 暴露 AVX。于是同一份程序、同一套环境、同一个镜像,昨天在 A上跑得好好的,今天到 B 上就 illegal instruction 了。

​ 本质上,变的不是你的代码,而是 VM 看到的 CPU 能力。 这一步特别值得强调,是因为大多数人遇到这种问题的第一反应都是去折腾用户态------重装 Python、重装 CUDA、重新编译PyTorch、换镜像版本,折腾一圈发现毫无效果。因为问题根本不在那一层:上面所有东西一个字节都没变,是底下那块"虚拟CPU"被换了。

​ 所以排查顺序应该反过来:先用 cat /proc/cpuinfo | grep flags 对比迁移前后的指令集差异,确认 CPU 能力是否一致,再去怀疑用户态。

7.4 Step4:确认是不是 SIMD 优化库触发的

​ 很多现代科学计算库为了性能,会默认启用SIMD、向量化、CPU 特化优化 。常见的"重灾区"包括:

  • numpy(尤其是带 MKL 的版本)
  • polars、pyarrow
  • pytorch、tensorflow、jax

​ 这些库的典型行为是运行时动态探测 CPU 能力,再挑一份最快的 kernel。检测到 AVX2 就走 AVX2 内核,检测到 AVX-512 就走AVX-512 内核。这套机制在裸机上工作得很好,但一旦放进虚拟机,就有几个地方会出岔子:

  • 检测逻辑误判:库读到的 CPU flags 和 VM 实际能执行的指令对不上

  • Guest 和 Host 信息不一致:VM 宣称支持 AVX2,但底下的 vCPU 模型其实砍掉了

  • wheel 编译目标过高:预编译包是在带 AVX-512 的机器上用 -mavx2 -mfma 打的,强制要求运行环境也具备这些指令

    程序加载 AVX2 指令

    CPU 实际不支持

    Illegal instruction

​ 这类问题最容易在一个场景下中招:pip install 装预编译 wheel。 因为PyPI 上很多包提供的是别人在高配机器上用 -mavx2 -mfma 甚至 -mavx512f 编出来的 wheel,整段二进制里都是硬编码的高级指令,它不做运行时探测,也没有降级路径,假设你的 CPU一定支持。一旦运行环境是个砍过指令集的 VM,程序连 import 都过不去就直接崩。

​ 排查思路也很直接:

  • python -c "import numpy; numpy.show_config()" 看看链接的是哪份后端
  • 怀疑是 wheel 问题时,加 --no-binary :all: 强制从源码本地编译,让编译器以当前 CPU为目标
  • 或者直接装"通用版本"(如 numpy 不带 MKL 的纯 OpenBLAS 构建),牺牲一点性能换可移植性

八、总结

​ 这次问题本质上不是Python问题,也不是Docker问题,而是VM 迁移后,CPU 模型退化成了 qemu64,导致 AVX 指令集被隐藏。最终导致polars 加载动态库时触发 SIGILL。

​ 这种问题非常"底层",但在 AI / 数据处理场景里会越来越常见。因为现在很多高性能库默认都假设 CPU 至少支持 AVX,所以以后看到:

复制代码
Illegal instruction (core dumped)

​ 不要只盯着代码,也要记得看看/proc/cpuinfo

相关推荐
AAI机器之心5 天前
在 macOS 上本地部署 Ollama + LLaMA3(附教程)
人工智能·macos·langchain·llm·知识库·大模型部署
liu****21 天前
LangGraph-AI应用开发框架(三)
人工智能·python·langchain·langgraph·大模型部署
handsomestWei1 个月前
华为昇腾DeepSeek模型部署
昇腾·ascend·huawei·大模型部署·deepseek
liu****1 个月前
LangChain-AI应用开发框架(二)
人工智能·python·langchain·大模型部署
YoanAILab1 个月前
大模型平台是怎么跑起来的?从 GPU 到 API 全链路拆解(工程视角)
大模型部署·ai平台·ai工程·ai基础设施·ai项目实战
长路 ㅤ   3 个月前
长路的AI领域技术博客汇总文档
向量数据库·大模型部署·langchain4j·智能体agent·ai后端技术
小C哈哈哈3 个月前
告别联网限制与隐私担忧:在自家电脑跑一个专属的DeepSeek AI
人工智能·lm studio·大模型部署·deepseek·本地部署模型
一切皆有可能!!3 个月前
昇腾atlas 300I duo部署Qwen3-8B完整实战:从选型到成功运行
人工智能·大模型·昇腾·大模型部署
阿尔的代码屋3 个月前
[大模型实战 01] 本地大模型初体验:Ollama 部署与 Python 调用指南
qwen·modelscope·大模型实战·ollama·大模型部署