首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >我在 32GB 单卡上跑两万四千专家的 MoE:分层放置实测与三个坑

我在 32GB 单卡上跑两万四千专家的 MoE:分层放置实测与三个坑

原创
作者头像
Archive
发布于 2026-10-29 15:52:42
发布于 2026-10-29 15:52:42
1520
举报
文章被收录于专栏:随笔随笔

一开始我是被一个数字吸引的:一张 32GB 显存的卡,配 64GB 内存,跑两万四千多个专家的 Qwen3.8-Flash-Next,出字每秒一百六七十个。作为参照,这个速度已经能应付不少后台任务了。

动手之后才发现,这件事跟"MoE 激活参数少"关系不大,甚至有反直觉的地方。记录一下。

一、第一个坑:MoE 省算力,不省内存

我最初的设想是:MoE 每个 Token 只激活一小撮专家,那我是不是只需要装那一小撮?

不是。没被唤醒的专家必须留在内存里待命,因为下一个 Token 轮到哪几个专家,是运行时由门控算出来的,事先不知道。省下来的只是"算"的那部分乘法。

用 Qwen3-30B-A3B 算一遍就很清楚了:

  • 总参数 300 亿
  • 每 Token 激活 30 亿
  • 按 8bit 装进去,权重大约 30GB

一张 32GB 的卡,装完权重基本就没剩什么了,连 KV 缓存都紧张。我当时的第一反应是"这不可能跑起来",第二反应是去查是不是量化档位选错了。

所以"激活 30 亿"这件事,只对算力有意义,对显存没有意义。这是第一个坑,也是最容易在选型时算错的地方。

二、跑起来靠的是分层,不是激活

真正让它跑起来的,是分层推理引擎(我用的是开源的 Strata)。它做了三件事,我拆开讲。

低比特量化。把权重从 8bit 继续往下压,占用字节跟着掉。公开实测用的是 IQ2_XS 这一档。这一步不新鲜,但它是后面所有分层能成立的前提——权重不够小,怎么摆都摆不下。

三层放置。这是核心:

  • 显存:放每次都要用的部分,剩下的空间做成"专家缓存",装最常用的那批。这个缓存随对话自适应,用得越久越知道该留谁。
  • 内存:钉住全部两万四千多个专家,一个都不许掉到盘上。
  • 固态盘:放一张 28.8GB 的短板表,供查词用,每个字只查几行。

长上下文还有一层。KV 缓存也照这个思路分:64K 以上只把常读的留在显存;读长文按 8192 token 一块读;引擎还会向专家缓存预留三千多个位置,装预填充阶段要用到的专家。

CPU 补位。缓存没命中的那次,权重来不及搬到显存,就让 CPU 就地算掉,同时 GPU 继续算命中的部分,两边不等。算当前层注意力的时候,下一层的专家已经在通过 PCIe 往显存流了。

参数结构大致是这样(参数名以你所用引擎的文档为准,这里只说明结构):

代码语言:bash
复制
# 示意:关键是"权重放哪一层"和"给显存留多少专家缓存"
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        # 草稿层加速

三、实测的账:七成专家覆盖九成八请求

分层之后数字是这样:

  • 32GB 显存的专家缓存占了 23.44GB
  • 里面装下一万七千多个专家,约为全部专家的七成
  • 命中率 97.8% 到 99.7%
  • 也就是一百次里不到三次要劳烦 CPU
  • 内存里钉着其余专家,CPU 开 23 个线程待命

七成装得下、九成八能命中,这个比例是我觉得最有意思的地方。它说明专家的访问分布很不均匀,热区很明显。如果分布是平的,这套缓存策略根本不会成立。

另外出字还有一层加速:模型自带一个猜字的草稿层,猜中多少就收多少,官方口径整体快 1.6 到 1.8 倍。那份实测里这层是开着的,这也是我本地配置打开它的原因。

顺带看到一个更极端的记录:官方基准里有 12GB 显存配 46GB 内存,跑 257GB 一档的模型,出字每秒九到十一个。显存每多 1GB,大约多放 700 个专家——这个换算关系挺实用,卡小就把 --experts-cache 开小点,不必硬套别人的配置。

四、第二个坑:速度数字必须连口径一起看

我一开始被"每秒一百多个 Token"冲昏头,实测发现起伏很大,后来才注意到口径。

那份报告写得很克制:九次测量,全部在同一台已经加载好的机器上串行跑,贪心解码,输出上限 256 Token。并明确写了一句——并发和长输出都没有测。

这就意味着三件事会立刻改变结论:

  • 并发:多人同时用,CPU 补位的线程会被抢,命中率不变但补位代价上升
  • 长输出:草稿层的收益只在部分场景明显,长文生成的整体速率会摊薄
  • 冷启动:模型没加载完时第一次响应慢得离谱,别拿它当稳态

所以我现在看任何端侧速度,先问这三件事,再看数字。

五、第三个坑:有人担心固态盘被读坏

这个顾虑我自己也有过,因为分层之后盘上确实有一大块东西在被频繁读取。

结论是:读取带来的磨损很小,真正值得盯的是写入。而端侧推理这个场景,主要是读。如果你在跑的场景会让盘上文件频繁重写(比如日志、缓存落盘),那才是要单独评估的。

六、什么活该放本地

跑通之后不要急着把什么都搬过来。这套方案换来的,是"快的那一层不用那么大",代价是拿搬运、调度和一部分 CPU 算力,去换显存容量。账并没有变少,只是换了个地方记。

我的划分是这样:

  • 放本地:高频、轻量、不想让数据出门的活。本地文档整理、内网资料问答、离线翻译、代码补全。
  • 走云:要跨几十份资料做长链推理的活。这种活对吞吐和上下文都敏感,端侧不划算。

对企业来说,这个边界是动态的:量大、单次轻、对隐私敏感的那一类,可以从云上挪下来;挪多少,按任务重新算一遍就行。

小结

端侧 MoE 最容易误读的一点,是把"激活得少"当成"占得少"。算力账确实省了,内存账一分没省。

端侧机器卡内存、卡功耗、也卡算力,其中内存最紧。所以这几年本地跑大模型的进展,更多来自存储和调度这一侧,而不是算力这一侧。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、第一个坑:MoE 省算力,不省内存
  • 二、跑起来靠的是分层,不是激活
  • 三、实测的账:七成专家覆盖九成八请求
  • 四、第二个坑:速度数字必须连口径一起看
  • 五、第三个坑:有人担心固态盘被读坏
  • 六、什么活该放本地
  • 小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档