很多刚上手 vLLM-Metal(基于 MLX Metal 后端)的开发者都会遇到同一个迷惑现象:
启动模型跑推理,打开 mac 活动监视器,GPU 面板看着几乎是 0%,第一反应:是不是回退到 CPU 跑了?
这是一个非常经典的误区:Apple Silicon 的 Metal GPU 监控逻辑,和 NVIDIA 的 nvidia-smi 完全不是一套体系,活动监视器的 GPU 图表不能作为 vLLM-Metal 负载的判断依据。
正确的监控方式:powermetrics
macOS 自带 powermetrics,是苹果官方的硬件性能采样工具,也是判断 M 系列芯片 Metal 真实负载最可靠的手段。
sudo powermetrics --samplers gpu_power -i 1000
-i 1000代表每 1000ms 采样一次,必须在正在生成 token 推理的时候采集数据,加载模型、空闲等待阶段 GPU 负载本身就很低。
一份真实负载日志解读
GPU HW active frequency: 754 MHz
GPU HW active residency: 100.00% (338 MHz: 0% 618 MHz: 24% 796 MHz: 76% 832 MHz: 0% 924 MHz: 0% 952 MHz: 0% 1056 MHz: 0% 1064 MHz: 0% 1182 MHz: 0% 1182 MHz: 0% 1312 MHz: 0% 1242 MHz: 0% 1380 MHz: 0%)
GPU SW requested state: (P1 : 0% P2 : 0% P3 : 0% P4 : 0% P5 : 0% P6 : 0% P7 : 0% P8 : 100% P9 : 0% P10 : 0% P11 : 0% P12 : 0% P13 : 0%)
GPU SW state: (SW_P1 : 0% SW_P2 : 24% SW_P3 : 76% SW_P4 : 0% SW_P5 : 0% SW_P6 : 0% SW_P7 : 0% SW_P8 : 0% SW_P9 : 0% SW_P10 : 0% SW_P11 : 0% SW_P12 : 0% SW_P13 : 0%)
GPU idle residency: 0.00%
GPU Power: 21200 mW
核心结论:这个样本里 GPU 已经满载
GPU HW active residency: 100.00%:硬件活跃占比 100%,GPU 无空闲,这才是 Apple Silicon 真正的 GPU 利用率指标GPU idle residency: 0.00%:空闲占比为 0,持续在干活GPU Power: 21200 mW = 21.2W:M 系列 GPU 跑到 21W+,属于很高的推理负载- 频率分布:24% 时间运行在 618MHz,76% 时间运行在 796MHz,加权平均 754MHz,和上面的
GPU HW active frequency完全吻合
系统固件会尝试拉高到更高 P 档(本例 P8),但受功耗墙、温控限制,硬件实际稳定在 SW_P2、SW_P3 两个频率点,属于正常的动态调频,不是故障。
为什么活动监视器看着很低?
活动监视器的 GPU 图表是一套老旧的统计口径,和 MLX /vLLM-Metal 的 Metal 内核负载统计不匹配,很容易出现 “GPU 明明在跑,图表不动” 的假象。 ✅ 判断 vLLM-Metal 是否走 GPU,优先看:HW active residency + GPU 功耗 ❌ 不要以活动监视器 GPU 面板为准
高频踩坑清单(GPU 没跑起来的排查)
- Python 是 Rosetta x86_64(最高发) vLLM-Metal 仅支持 arm64 原生 Python,x86_64 通过 Rosetta 运行会直接回退 CPU。
python -c "import platform;print(platform.machine())"
输出必须是 arm64;如果是x86_64,需要新建 arm64 虚拟环境。
- 系统版本不足 vLLM-Metal 预编译包要求 macOS 15 Sequoia 及以上,低版本无法加载 Metal 后端,自动降级 CPU。
- 环境变量强制切到 CPU
echo $VLLM_MLX_DEVICE
如果值是cpu,会完全不走 GPU。启动前设置:
export VLLM_MLX_DEVICE=gpu
export VLLM_METAL_USE_MLX=1
- 模型格式不匹配 优先使用
mlx-community量化模型,普通 HF Torch 模型不一定能落到 MLX Metal 算子。 - 内存不足自动降级 Apple 是统一内存,模型权重 + KV 缓存占用过高时,MLX 会把部分算子切到 CPU 执行,GPU residency 大幅下降。 启动参数调低显存利用率:
--gpu-memory-utilization 0.6
- 采样时机问题 单请求、短输出场景下,prefill 和解码很快,GPU 只是短暂 burst,powermetrics 采样窗口很容易抓不到满载;多并发压测才能稳定看到持续高 residency。
补充区分:vLLM-Metal ≠ PyTorch MPS。它是独立插件,走 MLX Metal 内核,
torch.mps相关监控命令对它无效。
附加小工具
1. actop(好看的 TUI 监控面板)
pip install actop
actop --proc-filter "vllm"
可以直接可视化查看 GPU residency、内存、进程负载,比 powermetrics 原始输出友好很多。
2. 精简 awk 脚本,只看核心指标
sudo powermetrics --samplers gpu_power -i 1000 | awk '/GPU HW active residency|GPU idle residency|GPU Power/ {print}'
小结
在 Mac 上跑 vLLM-Metal,一定要抛弃 NVIDIA 的监控思维: HW active residency 才是 M 芯片 GPU 真实负载的金标准,活动监视器只能当个参考,不能用来判断推理是否跑在 GPU 上。 持续 100% residency + 20W 以上功耗,说明你的 Metal 后端已经正常满载工作,不用怀疑。