
一开始我是被一个数字吸引的:一张 32GB 显存的卡,配 64GB 内存,跑两万四千多个专家的 Qwen3.8-Flash-Next,出字每秒一百六七十个。作为参照,这个速度已经能应付不少后台任务了。
动手之后才发现,这件事跟"MoE 激活参数少"关系不大,甚至有反直觉的地方。记录一下。
我最初的设想是:MoE 每个 Token 只激活一小撮专家,那我是不是只需要装那一小撮?
不是。没被唤醒的专家必须留在内存里待命,因为下一个 Token 轮到哪几个专家,是运行时由门控算出来的,事先不知道。省下来的只是"算"的那部分乘法。
用 Qwen3-30B-A3B 算一遍就很清楚了:
一张 32GB 的卡,装完权重基本就没剩什么了,连 KV 缓存都紧张。我当时的第一反应是"这不可能跑起来",第二反应是去查是不是量化档位选错了。
所以"激活 30 亿"这件事,只对算力有意义,对显存没有意义。这是第一个坑,也是最容易在选型时算错的地方。
真正让它跑起来的,是分层推理引擎(我用的是开源的 Strata)。它做了三件事,我拆开讲。
低比特量化。把权重从 8bit 继续往下压,占用字节跟着掉。公开实测用的是 IQ2_XS 这一档。这一步不新鲜,但它是后面所有分层能成立的前提——权重不够小,怎么摆都摆不下。
三层放置。这是核心:
长上下文还有一层。KV 缓存也照这个思路分:64K 以上只把常读的留在显存;读长文按 8192 token 一块读;引擎还会向专家缓存预留三千多个位置,装预填充阶段要用到的专家。
CPU 补位。缓存没命中的那次,权重来不及搬到显存,就让 CPU 就地算掉,同时 GPU 继续算命中的部分,两边不等。算当前层注意力的时候,下一层的专家已经在通过 PCIe 往显存流了。
参数结构大致是这样(参数名以你所用引擎的文档为准,这里只说明结构):
# 示意:关键是"权重放哪一层"和"给显存留多少专家缓存"
run-infer \
--model ./qwen3.8-flash-next-IQ2_XS.gguf \
--gpu-layers auto # 常驻算力层放显存
--experts-cache 23.44G # 显存里给专家缓存留的额度
--pin-experts ram # 其余专家全部钉在内存
--cpu-threads 23 # CPU 待命线程数
--ctx-size 65536 # 长上下文时 KV 缓存的活水位
--draft on # 草稿层加速分层之后数字是这样:
七成装得下、九成八能命中,这个比例是我觉得最有意思的地方。它说明专家的访问分布很不均匀,热区很明显。如果分布是平的,这套缓存策略根本不会成立。
另外出字还有一层加速:模型自带一个猜字的草稿层,猜中多少就收多少,官方口径整体快 1.6 到 1.8 倍。那份实测里这层是开着的,这也是我本地配置打开它的原因。
顺带看到一个更极端的记录:官方基准里有 12GB 显存配 46GB 内存,跑 257GB 一档的模型,出字每秒九到十一个。显存每多 1GB,大约多放 700 个专家——这个换算关系挺实用,卡小就把 --experts-cache 开小点,不必硬套别人的配置。
我一开始被"每秒一百多个 Token"冲昏头,实测发现起伏很大,后来才注意到口径。
那份报告写得很克制:九次测量,全部在同一台已经加载好的机器上串行跑,贪心解码,输出上限 256 Token。并明确写了一句——并发和长输出都没有测。
这就意味着三件事会立刻改变结论:
所以我现在看任何端侧速度,先问这三件事,再看数字。
这个顾虑我自己也有过,因为分层之后盘上确实有一大块东西在被频繁读取。
结论是:读取带来的磨损很小,真正值得盯的是写入。而端侧推理这个场景,主要是读。如果你在跑的场景会让盘上文件频繁重写(比如日志、缓存落盘),那才是要单独评估的。
跑通之后不要急着把什么都搬过来。这套方案换来的,是"快的那一层不用那么大",代价是拿搬运、调度和一部分 CPU 算力,去换显存容量。账并没有变少,只是换了个地方记。
我的划分是这样:
对企业来说,这个边界是动态的:量大、单次轻、对隐私敏感的那一类,可以从云上挪下来;挪多少,按任务重新算一遍就行。
端侧 MoE 最容易误读的一点,是把"激活得少"当成"占得少"。算力账确实省了,内存账一分没省。
端侧机器卡内存、卡功耗、也卡算力,其中内存最紧。所以这几年本地跑大模型的进展,更多来自存储和调度这一侧,而不是算力这一侧。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。