[控场AI]
· 7 分钟阅读· 3,868 字

12GB显卡跑68GB大模型:Betelgeuse引擎实测22 tok/s

12GB显卡跑68GB大模型:Betelgeuse引擎实测22 tok/s

Betelgeuse引擎让12GB显卡+16GB内存的普通PC以22 tok/s运行68GB MoE模型,且输出比特精确。

开发者发布推理引擎Betelgeuse,在RTX 3060 12GB加16GB DDR4的普通游戏PC上,以22 tok/s持续运行68GB的Qwen 3.8 Flash Next MoE模型,峰值可达48 tok/s,并保证与原始模型100%比特一致。此前他放弃的门控剪枝方案虽快却损害低比特模型质量。对比之下,stock llama.cpp因mmap页缓存颠簸仅1.47 tok/s,Strata在低内存下强制mmap后为8.11 tok/s。Betelgeuse通过零剪枝全专家计算、VRAM槽池、流内GPU门铃与单次CUDA Graph重放、RAM受害者缓存及io_uring分页,把物理SSD读取从约71MB/token降至12.43MB/token。作者正将其移植到DeepSeek V4.1 Flash,并已开源及向上游提交PR。

在消费级硬件上运行大模型,显存和内存往往是最大的瓶颈。一位开发者在Reddit上分享了名为Betelgeuse的推理引擎,声称能在RTX 3060 12GB显卡和16GB DDR4内存的普通游戏PC上,以22 tok/s的速度持续运行68GB的Qwen 3.8 Flash Next MoE模型,并且保证输出与原始模型100%比特一致。

reddit source: Betelgeuse: Running Qwen 3.8 Flash Next at 22 tok/s sustained (spiking to 48 tok/s) on an RTX 3060 1

背景:旧方案的妥协与新挑战

作者坦言,大约两个月前他曾尝试通过预测MoE专家激活来加速CPU/GPU卸载,但最终放弃了那个原型。原因是他当时使用了门控剪枝(gate pruning)——当路由权重较低时丢弃“冷”专家。虽然tok/s数字很好看,但在低比特量化模型上,这种做法的输出质量和推理能力会悄然下降。他不愿意为了截图上的速度而交付一个“脑叶切除”的模型。

当Qwen 3.8 Flash Next发布后,他决定挑战在普通预算游戏PC上以可用速度运行68GB的GSQ-RCO-IQ2_XS构建,且不丢弃任何一个专家。测试平台刻意还原了普通16GB内存PC的配置:RTX 3060 12GB、单通道DDR4 16GB(约19 GB/s)、CachyOS/Arch Linux(严格限制在MemoryMax=12G的cgroup内)、消费级PCIe NVMe SSD(约2.1 GB/s)。

MoE(混合专家)架构是理解本文的前提。传统稠密Transformer每生成一个token都要激活全部参数,而MoE层包含多个并行的“专家”前馈网络,由路由器(router)根据当前token的隐状态为每个专家打分,只挑选得分最高的若干个(top-k)参与计算。以文中模型为例,每层有10个路由专家,模型总参数因此可以远超显存容量,但单次推理只触碰其中一小部分,这正是“68GB模型跑在28GB可用内存上”在理论上可行的原因。代价是:未被选中的专家仍需在某处存放,一旦被换出到慢速存储,就会产生I/O瓶颈。

量化与比特精确也值得说明。GSQ-RCO-IQ2_XS、Q8_K_XL等命名属于llama.cpp的GGUF量化格式,数字越小表示权重压缩越激进(IQ2约为2比特级)。量化本身会引入误差,因此“100%比特一致”指的是:在相同量化权重、相同采样配置下,Betelgeuse的输出与原始推理栈逐字节相同,即加速没有额外改变模型行为。这与门控剪枝形成对比——后者直接跳过被判定为“冷”的专家,虽然省算力,却改变了计算结果,在低比特模型上误差会被放大。

原生llama.cpp与Strata的局限

在标准llama.cpp中加载68GB MoE到12GB VRAM+16GB RAM,结果可想而知:mmap导致操作系统页面缓存剧烈颠簸,每token约产生1500次主要页面错误,生成速度只有1.47 tok/s。

作者也测试了Strata。Strata在有48GB–64GB内存来mlock 24GB+专家时能跑到40+ tok/s,但在16GB内存环境下,除非强制使用--low-ram mmap,否则拒绝加载;而强制后速度降至8.11 tok/s,受限于冷SSD读取。

mmap与页缓存颠簸是这段性能对比的关键背景。llama.cpp默认用内存映射(mmap)把模型文件当作虚拟内存访问,由操作系统按需将文件页调入物理内存。当模型远大于RAM时,工作集频繁换入换出,每次访问未驻留页都会触发一次“主要页面错误”(major page fault),需要同步等待磁盘读取。文中“每token约1500次主要页面错误”意味着每生成一个词元就要经历上千次阻塞式磁盘访问,1.47 tok/s正是这一开销的直接体现。

mlock是Linux的系统调用,用于把指定内存页锁定在物理RAM中,禁止内核将其换出到swap。Strata在48–64GB内存的机器上通过mlock常驻24GB以上专家数据,因而能避开页缓存颠簸;但在16GB机器上,可锁定的内存不足,只能退回到mmap模式,性能随即崩塌。这也解释了为何“同样算法在不同内存容量上表现差异巨大”。

Betelgeuse的核心机制

Betelgeuse是llama.cpp的一个分支(bel-cli / bel-server),作者同时也在向上游提交PR。它通过多项创新在有限硬件上实现了突破:

零门控剪枝,100%比特精确

每一层全部48层中的全部10个路由专家都以全精度计算。作者用28,080条路由记录和576个生成token与原始stock输出进行了逐字节验证,差异为0.000e+00。

到达-松弛VRAM槽池(约5000槽)

所有49个稠密层+GDN+QSA+LM head保留在约3.2GB VRAM中。剩余VRAM容纳约5000个专家槽,非均匀分布:早期层0–4每层240槽(计算松弛为0ms),中间层92槽,尾部层60槽。

流内GPU门铃+单次CUDA Graph重放

不再让ggml_backend_sched每token拆分图48次去问CPU哪些专家缺失(这消耗约360ms/token的cudaStreamSynchronize),而是用自定义流内CUDA内核在设备上以约2µs解析命中,仅当专家缺失时才敲响映射的主机门铃。每层token嵌入也被暂存到CUDA0,使整个解码过程作为单次CUDA Graph重放运行。

CUDA Graph是NVIDIA提供的一种执行优化:把一串GPU内核启动和内存操作预先录制为一张图,之后每次重放只需一次提交,从而消除大量主机端启动开销与同步等待。问题在于,MoE推理中“哪些专家在VRAM里”是动态变化的,传统做法需要CPU逐层检查并按需拆分计算图,这种主机-设备往返(文中提到每token约360ms的cudaStreamSynchronize)会彻底抵消CUDA Graph的收益。Betelgeuse的做法是把命中判断下沉到GPU上的一个轻量内核,仅在确实缺专家时才通过“门铃”通知主机,从而使整个解码过程可以固定为一张图反复重放。

RAM受害者缓存+io_uring分页器

当专家从VRAM池被逐出时,它移入专用的主机RAM受害者缓存而非被丢弃。VRAM和RAM保持100%互斥,避免在OS页面缓存中重复相同的热专家。物理NVMe读取从约71 MB/token降至12.43 MB/token。

无重复的35GB专家膨胀

不再在Shard 1 .gguf和experts.bin中各保留35GB死专家张量,而是从Shard 1中剥离专家负载,使主GGUF仅为3.2GB(Dense.gguf)+35.3GB(experts.bin,4KB对齐单读块)+26.8GB(PLE.gguf n-gram分片)。

实测结果

在RTX 3060 12GB+16GB DDR4、MemoryMax=12G环境下:

  • Stock llama.cpp (mmap):冷启动1.47 tok/s,热启动1.63 tok/s,峰值约2 tok/s,提示处理14–20 tok/s,物理SSD读取208–312 MiB/tok。
  • Strata (--low-ram mmap):冷热均为8.11 tok/s,峰值约9 tok/s,提示处理34.6 tok/s,池等待约105ms,输出KL散度0.022。
  • Betelgeuse (bel-server):冷启动16.80 tok/s,热启动22.03 tok/s,峰值最高48 tok/s,提示处理16.2–19.3 tok/s,物理SSD读取12.43 MiB/tok,输出100%字节精确。

热运行时,在长编码提示上能保持21.8–22.03 tok/s的持续速度;当生成遇到全部10个路由专家都驻留在VRAM/受害者池的片段时,速度可飙升至48 tok/s。

即使在约190GB总大小的Q8_K_XL量化上,bel-server在完全相同的12GB 3060+16GB DDR4机器上也能冷启动8 tok/s、热启动12 tok/s(峰值21 tok/s),而stock llama.cpp会立即OOM或爬行在<0.1 tok/s。

未来计划

作者正在将这套流式+受害者缓存架构移植到DeepSeek广告 V4.1 Flash(1017),早期测试在同类硬件上已达到约25 tok/s。项目已在GitHub开源(Betelgeuse-AI/Betelgeuse),并在HuggingFace提供了预打包的Alpha-Orionis-XS 3.2GB Dense+Experts捆绑包,同时向上游llama.cpp提交了PR。

对于拥有普通游戏PC的开发者来说,这或许意味着能在本地运行更大、更强的MoE模型,而无需牺牲输出质量。

#Betelgeuse#Qwen 3.8 Flash Next#MoE模型推理#llama.cpp#RTX 3060#本地大模型#比特精确
分享:

相关推荐