
上周我把一个总参数350亿的大模型完整地压进了一台普通旗舰手机里。点亮屏幕后随便问了句“介绍一下你自己”后台看了一眼内存占用9.6GB机身温度稳定在41度生成速度在6到9个token之间跳动。这个数字放到台式机上寒碜得没法看但放在内存墙这么陡峭的限制条件下已经是我折腾一周后能拿得出手的最好结果。这篇文章把这个折腾过程完整记下来先从内存墙到底是什么讲起再拆解350亿参数凭什么能塞进一台16GB手机然后讲手机SoC上哪些参数才是真正的瓶颈最后给出一套可复现的量化、部署和调参流程。适合两类人看一类是准备做端侧AI部署的工程师另一类是好奇“大模型到底怎么跑在手机里”的深度发烧友。看完你至少能自己判断手头这台手机能不能跑、能跑多快以及厂商发布会上说“35B端侧模型”时到底在说哪种模型。1. 先拆“内存墙”350亿参数到底吃了多少内存1.1 算一笔内存账从FP16到INT4先说一个基础的算账方法。模型权重占用的内存等于“参数个数乘以单个参数的字节数”。350亿参数写作35B按不同精度去算精度单参数占用350亿参数权重总量部署处境FP324字节140GB服务器单卡都吃力FP16/BF162字节70GBA100单卡勉强手机不用想INT81字节35GB工作站内存显卡大概可行INT40.5字节17.5GB旗舰手机内存的边缘极限INT4 MoE部分激活0.5字节 × 激活比例权重侧约5~9GB端侧真正可行的区间这个账才是“内存墙”第一层冲击的来源。70GB是什么概念A100单卡80GB装下FP16的350亿参数之后只剩10GB跑上下文单卡干活已经非常紧张INT8的35GB也得在64GB内存的工作站上才玩得转。而一台旗舰手机就算堆到16GB运行内存系统再吃掉3~4GB真正留给大模型进程的通常只剩12GB上下。所以问题摆在眼前想让350亿参数“住进”手机至少要把内存占用压到个位数GB这已经不是普通精度调整能做到的事。所以看到“350亿参数住进一台手机”这种宣传时第一反应不应该是“怎么可能”而是应该问一句模型权重被压成了什么精度模型结构是不是MoE这类不全量激活的类型。后面几节我会逐步展开。这里还要补一笔账这只是权重部分真正跑起来还有KV Cache。自回归解码时每一层的Key和Value都要暂存上下文越长存得越多。7B模型在4096上下文时KV Cache通常占200~600MB到了35B量级、上下文拉到8K以上KV Cache可以膨胀到几个GB。你以为把权重装进去就完事了其实内存墙背后还站着一个叫KV Cache的小弟专门在你切换长上下文场景时落井下石。1.2 容量墙之外还有带宽墙内存墙还有第二层带宽。这是很多刚上手的人最容易忽略的地方。大模型推理是自回归的生成下一个token时需要把权重从头到尾扫一遍。换句话说每生成一个token就要把“模型权重加上对应的KV Cache增量”从内存搬到计算单元。这个任务的瓶颈不是算力能算多快而是内存能喂多快。打个比方。厨房里五个大厨算力哪怕刀工再好传菜通道内存带宽一次只能端两盘菜客人照样得等。模型越大菜越多通道越窄等待越久。这就是为什么很多人在手机上跑大模型时会发现CPU占用不高、NPU也没满负荷但token每秒就是上不去——因为都被“交通拥堵”卡死了。手机的内存带宽到底有多窄主流旗舰机的LPDDR5X64bit位宽跑8533MT/s时理论带宽约68GB/s少数堆双通道的机型能到130GB/s以上。作为对比一张RTX 4090的GDDR6X显存带宽约1TB/s数据中心里的H100级别加速卡带宽约3.35TB/s。一部手机内存带宽只有顶级加速卡的几十分之一。这就是内存墙最现实的面貌不只是塞不下更是喂不饱。“塞不下”出容量墙“喂不饱”出带宽墙。两者共同回答了一个问题为什么服务器上的模型参数规模可以轻松跑到几千亿而手机端能舒服跑起来的很长时间只有7B、14B这种小不点。2. 往手机里塞参数的三板斧量化、稀疏、架构换血2.1 量化从70GB压到17.5GB的关键一步量化是把连续浮点权重映射到低bit整数的过程。原理上有点像把一张照片从RAW格式压缩成JPEG信息确实有损失但人眼或者说模型的下游任务经常感知不到。目前端侧用得最多的有三种RTNRound to Nearest直接就近取整简单粗暴不需要校准数据GPTQ逐层扫描用二阶信息补偿量化误差在4bit甚至3bit下质量更稳AWQ从激活值角度找敏感通道给它们单独做缩放保护推理速度损失小。量化的“参数”远不止比特数这么简单。列一个我常用的对照表量化参数作用常见取值经验group size多少个连续权重共享一组缩放系数32/64/128128在7B上性价比高35B我倾向128或256sym / asym是否允许非对称零点sym / asym激活带明显偏移时asym更稳校准样本量用多少真实分布数据调缩放128~1024条不是越多越好要贴近真实使用校准序列长度每条样本的token长度1024~2048太短覆盖不住长依赖为什么端侧默认值大多落在4bit因为从FP16降到INT4内存直接砍到原来的四分之一带宽压力同步大比例下降从4bit再往2bit走权重确实只剩8.75GB容量很诱人但质量损失开始不可控很多模型会出现明显胡言乱语。至少在350亿这个规模上我的结论是先试4bit质量不行再降档到3bit盲目冲2bit是给自己挖坑。2.2 剪枝与稀疏原理很美手机端难吃到肉剪枝这条路纸上非常漂亮砍掉一部分不重要的连接模型体积变小带宽也变小。结构化剪枝按行、列、通道删非结构化剪枝按单个权重删。问题是手机端的CPU、GPU、NPU对稀疏计算的支持非常有限。非结构化剪枝会让权重矩阵变得千疮百孔通用矩阵乘法引擎遇到这种稀疏矩阵效率反而大幅下降。手机上又没有数据中心那种专门的稀疏加速器很多宣传里的“90%稀疏”到了端侧省下磁盘空间是真的但推理速度未必变快有时候还会更慢。所以我的实操经验是如果目标是“把模型塞进手机跑起来”剪枝可以作为压缩前置步骤但不要指望它单独解决内存墙真正的肉戏还是在量化和架构上。这个方向更适合服务器端有专有稀疏算力、且对精度要求极高的大规模场景。2.3 架构换血MoE才是“350亿住进手机”的正解这里要区分两个概念总参数和激活参数。普通Dense模型每次推理所有参数都会参与计算350亿就是350亿一点折扣都不打。MoE混合专家模型则不同它把网络拆成“一个路由器加若干个专家”每次来一个token路由器只挑选其中一小部分专家来干活。也就是说一个总参数350亿的MoE模型激活参数可能只有10B左右。这对内存墙是决定性的。因为自回归模型每生成一个token要把“激活参数”那段权重从内存搬到计算单元。总参数不变没关系只要激活参数小每次搬运的数据量就小带宽墙的压力骤减再配合4bit量化10B激活参数的权重占用只有5GB上下手机16GB内存完全扛得住容量墙也破了。所以厂商说“350亿参数端侧运行”大概率说的是MoE而不是35B的Dense模型。两者体验差距巨大Dense 35B在手机上哪怕量化后权重也接近18GB现实里很难整机常驻MoE 35B却可以在按需调度和文件映射的帮助下把主路径压进10GB以内。理解这一点再讨论“住进手机”才有共同语言。3. 手机SoC怎么喂这个模型算力不是天花板带宽才是3.1 从CPU天梯图看到关键却被忽略的参数很多人挑手机习惯看CPU天梯图、手机SoC天梯图比对CPU大核频率、GPU浮点算力。这些数字在跑游戏时很有参考价值但在跑大模型这件事上最容易误导人。大模型推理是典型的memory-bound任务不像游戏那样光靠强劲执行单元就能让帧率翻倍。端侧跑一个LLM时算力利用率往往只有个位数百分比真正决定生成速度的是内存控制器带宽、缓存体系配合、以及NPU/CPU的访存模式。可以把SoC想象成一个港口算力单元是装卸工内存带宽是港口的吞吐管线。装卸工再多管线就那几条货照样走得慢。那么去哪里看内存带宽一般看LPDDR5X型号和位宽。旗舰机用LPDDR5X-853364bit位宽约68GB/s128bit位宽的堆料机型能过130GB/s。这个数字比盯着骁龙还是天玑的第几代更值得花时间。我还见过有人拿“NPU算力500TOPS”当卖点但实际跑LLM时NPU利用率上不去的话标称算力就是纸面数字。3.2 带宽公式算出来的token速度天花板我们可以先算一个理论天花板再和实测对比。生成速度token/s约等于“有效可用带宽除以每个token需要搬运的字节数”。每个token至少要搬运全部激活参数的权重字节加上少量KV Cache增量。比如一个7B Dense模型4bit量化后权重大约3.5GB在68GB/s带宽的手机上理论上限是19 token/s左右。实测能做到13~18 token/s已经相当接近剩下的损耗来自内存刷新、调度和KV Cache。再看350亿总参数的MoE模型激活参数取10BINT4后约5GB同样按68GB/s算理论上限是13.6 token/s。我的真机实测大概在5~9 token/s明显低于理论上限因为这类模型的层数、专家切换逻辑更复杂KV Cache、路由开销、PreFill阶段负担都更重。但即便如此5~9 token/s也足够做一问一答式的离线助手了。这个公式还能解释一个反直觉现象为什么7B模型在手机上普遍能跑十几token/s体感并不比服务器版慢太多因为服务器虽然带宽高但模型也大两者的比值常常落在一个数量级。换句话说内存墙把端侧和云端拉到了同一个极限尺度上只是墙的位置不同。3.3 异构调度CPU、GPU还是NPU我的实测结论端侧跑LLM硬件选择并不像想象中“NPU一定最快”。我的实际体验是CPU通用性最好内存访问模式灵活llama.cpp这类框架把CPU调度打磨得很充分。手机大核全开时7B INT4能稳定在14~18 token/s发热也在可控范围。GPU算力最强但驱动和内存分配限制多很多手机GPU对不规则内存访问不友好跑起来不见得比CPU快。NPU矩阵运算能效高但工具链往往要求固定shape、特定layout一旦对话变长或模型结构不够规整编译适配成本很大。在端侧推理框架成熟度参差不齐的背景下我的选择通常是“默认CPU只在厂商提供了完整SDK的机型上尝试NPU”。还有一个非常现实的点手机端推理要小心系统在后台做内存压缩、回收。模型权重如果能用mmap文件映射进内存可以减轻频繁换页的开销但系统判断内存吃紧时杀进程的优先级反而比普通应用更高。所以做端侧部署的人要学会看“内存占用和后台存活”这两个隐藏参数而不只是盯着算力指标。4. 端侧部署实操记录从量化参数到真机跑通4.1 模型转格式与量化档位的选择真机部署第一步把Hugging Face格式转成适合手机的文件格式。我日常用llama.cpp和MLC-LLM两条路各有各的忠实用户。llama.cpp的流程大致是# 先把HF模型转成GGUF python convert_hf_to_gguf.py ./model_dir --outfile model-fp16.gguf # 再做4bit量化 llama-quantize model-fp16.gguf model-Q4_K_M.gguf Q4_K_MQ4_K_M是4bit的k-quant变体兼顾体积、速度和质量是我在手机上默认的首选档位。想再省内存可以试IQ4_XS想要更好质量则选Q5_K_M。这几个名字看着花哨本质就是“比特数加量化策略”的组合。我的建议是不要只看4bit这个数字要把量化类型、group size甚至校准集一起纳入选择。MLC-LLM的用法稍有不同它把模型编译成对应后端的动态库量化档位在编译阶段固定mlc_llm convert_weight --quantization q4f16_1 mlc_llm compile --target androidq4f16_1这个标识符的含义是权重用4bit激活用16bit浮点KV Cache用特定分组策略。编译完成后把产物装进手机所有部署参数固化在包里运行时不需要再加载Python环境。相比llama.cpp可以随时换量化文件MLC-LLM更接近“出厂即成品”的思路但改参数要重新编译迭代成本高。4.2 手机端运行参数逐项拆解部署到手机后一组关键运行参数决定实际体验。我在Android设备上常用的命令大致长这样./main -m /sdcard/models/model-Q4_K_M.gguf \ -ngl 0 -t 4 -c 4096 \ --temp 0.7 --top-p 0.9 --repeat-penalty 1.1-ngl 0表示所有层都跑CPU。在部分手机GPU驱动不完善的条件下强行offload到GPU反而更慢0这个值听起来保守实测往往最稳。-t 4线程数。手机大核通常就4个左右盲目加线程只会增加调度切换开销甚至挤占系统资源。-c 4096上下文长度。每加大一截KV Cache占用就线性上涨4096是端侧“能聊日常话、又不过度吃内存”的甜点值。--temp / --top-p / --repeat-penalty解码质量参数。代码或数学问答压低温度闲聊稍微放开这些属于“结果参数”层面的事后面专门说。有两个参数要专门提醒不要开--mlock。端侧一旦锁页系统无法回收模型内存容易被后台机制杀掉或者和系统抢内存导致整机卡顿。不要一开始就把上下文拉满到16K或32K。部署350亿级MoE模型时KV Cache会迅速吃掉好几个GB速度直接对半砍体验瞬间从“能用”跌到“劝退”。4.3 真机实测数据与指标解读我整理了一份个人实测与社区常见数据混合的参考表。硬件、系统版本、室温都会影响结果别当出厂基准当数量级参考更合适。设备模型规模量化内存占用实测速度骁龙8 Gen3手机7B DenseINT4约4GB13~18 token/s骁龙8 Elite手机35B总参MoE激活约10BINT4约8~10GB5~9 token/s苹果M系列移动平台35B总参MoE激活约10BINT4约8GB10~15 token/s这些数字背后有几个一致的现象第一持续运行10分钟后降频会拉低速度峰值token/s只能维持几分钟第二电池温度超过43度后系统的温控策略会进一步收紧。所以内存墙落到手机上的最终形态往往不是某一项指标的断崖而是算力、带宽、功耗、散热四者同时逼近边界。发布会上的PPT参数之外真正要看的是这台机器在20分钟压力测试后的速度曲线。5. 模型参数之外的参数部署中要重新校准的隐藏成本5.1 量化参数踩坑实录校准集比想象中更影响质量第一个坑是校准集的语言分布。量化不是简单四舍五入需要一组代表真实分布的样本去调节缩放系数。如果模型主要在中文场景使用我却用纯英文语料做校准量化后的中文token分布会出现肉眼可见的漂移极端情况下回答变口语化、丢字、逻辑松散。任何模型的参数校准本质都是让压缩后的分布在原分布上尽量不漂移校准样本集就是那个“原分布”的代言人。第二个坑是校准样本量。拿几万条数据扫一遍并不比挑几百条高质量、贴近真实prompt的样本更好。样本越杂缩放系数越容易趋向平庸反而把关键通道的敏感度磨平了。我踩过的做法是从真实任务里找256~1024条覆盖常见问法的样本再做一次量化评估对比量化前后在同一组问题上的输出漂移漂移大就换group size或换量化档位。第三个坑是group size。它对内存占用和质量都有影响group size越小量化粒度越细精度越高但缩放系数存储开销也更大。在手机这样内存紧张的地方128是很均衡的起点如果发现质量不足再往64试而不要一下跳到32否则内存占用回升快前面省下的容量墙优势会被吃掉。提示我见过不少人在手机上只测“跑通了”“内存占用低”就认为量化成功这是危险信号。量化后的模型必须用固定评测集做回归同一批问题压缩前压缩后各跑一遍逐条看回答是否明显退化。端侧部署最怕的不是跑不快而是跑得快但输出质量崩了。5.2 解码参数、上下文长度与结果参数的解释口径模型跑通之后真正影响日常使用的反而是那些运行参数和结果参数。解码侧temperature、top_p、repeat_penalty对输出质量影响很大。端侧普遍是逐token生成batch size固定为1这些参数更要按任务分开调代码生成、数学题temperature设0.1~0.3确定性优先闲谈、创意写作temperature设0.8~1.0中文场景下repeat_penalty可以放在1.05~1.15太低容易复读太高会让口语变生硬。上下文长度是另一个容易被忽略的隐形参数。我部署时总跟同事说不要去抢最高的context window要看KV Cache和带宽的乘积。以350亿级MoE举例8K上下文对应的KV Cache可以到2~4GB不仅挤占模型权重空间还会让每个token的搬运量上升实测速度可能掉到5 token/s以下。因此除非任务真的需要长文档我一般建议端侧先锁4K等测出吞吐量再逐步加。最后看结果参数。跑完一轮部署不要只看“能回答问题”就收工要把这些指标都记下来内存峰值、稳态token/s、首token延迟、电池温度曲线、掉帧概率、异常输出比例。这些才是解释部署效果的关键口径。还有一个常被忽略的点如果系统在后台对模型内存做压缩推理速度会周期性掉档所以要看的是“10分钟均值”而不是“第一句的速度”。5.3 端侧大模型的新场景在哪里放到更长的链条上看350亿参数能住进手机直接改变了几类场景的可行性。隐私敏感的本地任务可以不用上传云端会议纪要、个人助理、本地知识库问答这类数据不出机从根上躲开传输链路。离线环境下的对话能力也不再靠云端兜底飞机、地铁、偏远地区一部手机就是一个小型智能终端。车机、工业巡检设备这类对延迟和断网敏感的地方端侧35B模型的出现更是让“本地AI大脑”从一个PPT概念变成可运行方案。这些应用方向不是把云端模型简单搬进手机而是重新围绕内存墙设计模型结构和推理路径整套思路会反过来影响新一代端侧芯片的设计取舍。对于动手尝试的人我的实操建议是不要一步跨到350亿那一级先在手头的旧手机或电脑上跑通一个7B模型的INT4量化把llama.cpp或MLC-LLM的流程摸一遍理解量化档位、上下文长度、线程数和内存这四个参数之间的博弈。等你能不靠文档回答“为什么7B在手机上跑14 token/s、理论上限却算出19”这个问题时再上35B级MoE也不迟。我个人踩了几次坑之后保留的折中方案是350亿量级的MoE模型量化后放手机上做离线问答和快速草稿真正复杂的长任务还是交给云端大模型。内存墙之下懂取舍比懂堆料更值钱。如果你也想动手验证先从资源需求最低的7B模型开始今晚就能看到第一个token从手机里蹦出来。