苹果虚拟机跑本地大模型慢 16 倍,一个补丁补回来

在苹果芯片的 Mac 上跑大模型,很多人会选择 llama.cpp。但当它运行在 macOS 虚拟机里时,推理速度可能只有裸机的一小部分。开源项目 Cua 近日发布的一项测试结果给出了原因,也给出了解法:只要在虚拟机里补一层进程级的 Metal 能力补丁,llama.cpp 的提示处理速度最高可提升约 11 倍,生成速度最高提升约 16 倍。

Cua 的团队此前以 macOS 虚拟化栈 Lume 起步。苹果自家的 Virtualization.framework 让 macOS 客户机通过虚拟 GPU 使用宿主的 Apple GPU,但在默认配置下,这个虚拟设备上报了一套非常保守的 Metal 能力档。应用程序正是根据这些应答来选择计算内核和渲染路径,于是 llama.cpp 在虚拟机里走了更慢的 GPU 代码路径。

虚拟机里的 GPU 被「降级」了

问题出在能力查询的应答上。在 Cua 基于 macOS Tahoe 的标准虚拟机里,这块虚拟显卡上报的近似能力是「Apple 5 时代家族」、最大线程组内存仅 32 KB,并且不支持 SIMD 组矩阵运算。现代 Metal 软件会依据这些应答挑选内核,即便设备其实能跑更新的内核,llama.cpp 也只会选择更慢的实现。

苹果官方文档通过「GPU 家族与特性表」来描述 GPU 能力,并建议应用在运行时查询设备。换言之,应用程序只是照着平台告诉它的边界来工作。这与常见的 GPU 直通不同:在 x86 Linux 上可以通过 VFIO 把物理 PCI 设备直接分配给虚拟机,而苹果这套是半虚拟化架构,宿主机仍掌控硬件,客户机使用的是虚拟化感知的设备。

进程级补丁做了什么

Cua 团队写了一个很小的 Metal 能力补丁,作为兼容层插在某个客户机进程与 Metal API 之间。它只拦截并改写该进程读到的少数几项能力应答:把支持的家族档提升到 Apple family 9(编号 1009),并把最大线程组内存从 32 KB 提到 64 KB。就这两项改动,足以让被测的 llama.cpp 版本改用更新的 SIMD 组归约、SIMD 组矩阵与 bfloat16 路径。

关键在于,这个补丁只作用于被注入的那个工作进程及其子进程,工作负载仍然跑在苹果现有的虚拟 GPU 通道上,由宿主的 Apple GPU 执行;它不涉及物理 GPU 直连、原始 PCI 或 VFIO 直通,也不改动内核。其余能力档保持默认不变,配置缺失或格式错误时会自动回落到标准路径。

实测:提速 7 到 16 倍

测试在一台 Apple M1 Ultra(48 核 GPU)、宿主 macOS 26.6.1 上进行,客户机为当前公开的 Tahoe Cua 镜像(macOS 26.5.2、8 个虚拟 CPU、16 GiB 内存),运行 Lume 0.5.1,统一使用官方 llama.cpp b10167 版本。

使用 TinyLlama 1.1B 对话模型(Q4_K_M)时,提示处理从标准虚拟机的每秒 431.86 个词元提升到解锁后的 4786.70 个词元,达到裸机的 98.25%;生成速度从每秒 12.63 个词元提升到 206.60 个词元,相当于裸机的 72.06%。两项提升分别为 11.08 倍与 16.36 倍。

换成 Google 今年发布的 Gemma 4 12B(QAT Q4_0,约 6.98 GB)后,提示处理从每秒 71.66 个词元提升到 515.76 个词元,达到裸机的 99.59%;生成从每秒 3.41 个词元提升到 49.67 个词元,相当于裸机的 94.82%,提升分别为 7.20 倍与 14.54 倍。

再用 Meta 官方的 Muse Glimmer 30B(Q4_K-M,约 16.76 GB,客户机内存提到 64 GiB)测试,提示处理从每秒 25.83 个词元提升到 194.97 个词元,生成从每秒 2.38 个词元提升到 21.08 个词元,提升分别为 7.55 倍与 8.87 倍。作为对照,MLX-LM 0.31.3 在标准中就已经很快,补丁前后几乎持平(提示 1.005 倍、生成 0.993 倍),这也帮助团队定义了发布时所覆盖的能力档范围。

局限与适用边界

这项技术仍是实验性的,且对版本敏感:它依赖客户机 Metal 实现中私有的、随 macOS 版本可能变化的行为,因此每一个宿主与客户机组合都需要单独验证。补丁只影响被注入的工作负载,加固或受平台保护的程序可能拒绝库注入;它覆盖的能力档也仅限于已测试的范围,物理 GPU 能力发现不在其内。

Cua 已将相关源码以与 Lume、Cua 相同的宽松许可证开放,并附带构建脚本、能力探测与原始基准日志,供他人复现。对于需要在苹果芯片虚拟机里跑本地推理的开发者,这层补丁提供了一个值得关注的起点——前提是接受它的实验属性,并为每个系统组合自行核验。

来源:Cua 官方博客(GitHub 项目 trycua/cua),作者 Francesco Bonacci 与 Johnny Franks