在板子或手机上跑模型,卡人的往往不是算法,而是「跑不起来」:权重下不动、内存爆了、首帧太慢、换个机型又崩。这篇不讲论文,按部署顺序给你一条能照着做的路径——怎么定约束、怎么挑权重、怎么量化、怎么测、怎么打包,以及每步该拿什么指标验收。
在板子或手机上跑模型,卡人的往往不是算法,而是「跑不起来」:权重下不动、内存爆了、首帧太慢、换个机型又崩。这篇不讲论文,按部署顺序给你一条能照着做的路径——怎么定约束、怎么挑权重、怎么量化、怎么测、怎么打包,以及每步该拿什么指标验收。
先把预期摆正:端侧部署是工程活,不是调参比赛。同一份权重在不同芯片、不同运行时、不同系统版本上表现能差出一大截,所以下面每一步都强调「先量化自己的条件,再去挑方案」,而不是反过来照着别人的配置单抄。
先把约束写死:端侧部署到底在跟谁较劲
端侧和服务器推理的差别不在模型大小,而在内存上限、功耗墙、散热和没有运维窗口这四件事。服务器上内存不够就加机器,端侧内存不够就是直接崩;服务器烫了有风扇,手机烫了系统会限频,速度断崖式下滑,而你没法登录上去重启。
- 可接受延迟:首字多久算合格,稳定输出多快算合格,分别写数字
- 可用内存:留给模型和运行时的上限是多少,不是设备总内存
- 模型体积上限:安装包或权重下发通道能承受多大
- 是否要离线:全程离线还是允许首次联网拉权重,这决定了打包方式
- 目标机型下限:最低配那一档必须跑得起来,后面的测试都对着它做
| 约束项 | 为什么先定 | 定不下来会怎样 |
|---|---|---|
| 延迟上限 | 决定量化档位和模型尺寸的取舍空间 | 优化到一半才发现目标达不到,前面白做 |
| 内存上限 | 决定能不能整块加载,还是要分片或卸载 | 设备上随机崩溃,且难复现 |
| 体积上限 | 决定权重是内置还是下发 | 安装包被渠道打回,或下载转化明显变差 |
| 离线要求 | 决定运行时依赖和授权校验怎么写 | 上线前才发现需要联网激活,方案推翻 |
选底座:不追榜单,按「能塞进去」倒推
很多人选底座的顺序是先看效果榜,再看能不能跑,结果反复返工。正确的顺序是反过来的:先按可用内存倒推参数量与量化档位,再看这个档位下有哪些候选权重。能塞进去是入场券,效果是在入场之后才比较的事。
- 第一步:算可用预算用内存上限减去系统和其他业务占用的部分,剩下的才是模型可用额度,这个数字写进约束表。
- 第二步:列候选同尺寸档位下找出几个候选权重,记录参数量区间、目标加速器是否已支持、是否需要自己做权重转换。
- 第三步:查许可证端侧是随 App 或硬件出货的,商用边界和再分发条款这一条比效果更早卡人,不确定的直接划掉。
- 第四步:做最小验证把剩下的候选各跑一次最小推理,只验证能不能加载、能不能出结果、内存峰值多少,不比较效果。
同尺寸下优先挑推理框架已有现成实现的架构。冷门结构往往需要自己写算子或回退到 CPU 执行,回退到 CPU 之后延迟基本就没法看了。判断方法很简单:去目标运行时的支持列表里查一眼,查不到就当作不支持。
量化档位怎么定:精度、体积、速度的三方拉扯
量化不是越小越好。低比特会先伤到长输出连贯性和数值推理能力,短指令类任务通常更耐受。换句话说,你得先想清楚自己的任务属于哪一类,再决定压到哪一档。
| 任务类型 | 可以采取的档位策略 | 判断依据 |
|---|---|---|
| 分类、抽取、关键词 | 相对激进地压,优先换体积和速度 | 输出空间小,错误容易被后处理兜住 |
| 短指令对话 | 中等档位,留一点余量 | 偶尔的重复和跑偏用户能接受 |
| 开放生成、数学推理 | 保守,宁可大一点 | 一旦塌陷整段输出都不可用 |
| 多语言或长文档 | 按最长输入单独验 | 上下文长时表现和短输入差别很大 |
还有一点容易忽略:同一份权重在不同运行时的实际表现不一样,所以选档位时要连着运行时一起选,不能只比文件大小。验收动作是拿一批你自己的真实输入,对比压缩前后的输出差异,差异超出容忍范围就退回上一档。不要用公开榜单代替这一步,榜单的输入分布和你业务的输入分布基本不是一回事。
内存与显存预算:把每一项加起来,别拍脑袋
只算权重是最常见的翻车点。真实占用至少包含四块:权重、运行时缓存、输入输出张量、框架自身开销。后三块在小模型上占比不显眼,但模型越小、上下文越长,它们的相对占比就越大。
- 权重:按量化后的字节数估,别按原始精度算
- 运行时缓存:框架自己的池子和临时缓冲区,跑起来才知道,最好实测
- 输入输出张量:图像、音频这类输入尺寸固定但很大,务必单列
- 长上下文:中间的键值缓存随长度增长,长文本场景要单独算这一项
内存不够时的解法有优先级:先降上下文,再降量化档位,再考虑把部分算子卸载到 CPU,最后才动模型尺寸。顺序别乱,因为动模型尺寸意味着前面的量化验证全部作废重做,成本最高。
算完自己的数字之后,去站内的模型资料库核对同类配置的实际记录,看看别人的实测和你的理论值差多少。如果差得远,先怀疑自己的估算漏项,而不是怀疑记录不准。具体数字到站内页面看当时的记录。
把速度调出来:从「能跑」到「能用」的排查顺序
先测基线再优化,这是唯一能判断优化是否生效的办法。基线要分三项记:冷启动、首字延迟、稳定输出速度。缺哪一项都会误判瓶颈,比如只记总耗时,就分不清是加载慢还是算得慢。
- 确认加速器真被用上查运行时的后端日志或状态接口,确认算子确实在目标加速器上执行,而不是静默回退到 CPU。
- 看输入处理与分词图像预处理、重采样、分词这些环节经常吃掉可观时间,先把它们和模型计算分开计时。
- 查权重是否反复加载每次请求都重新读盘加载权重,是端侧很常见的低级问题,确认加载只做一次。
- 调线程数线程不是越多越快,超过物理核数之后经常反而更慢,按核数附近做几组对比。
- 最后才换量化档位前面几步都排干净了还是不够快,再考虑更激进的量化,并且要重新跑一遍输出质量验收。
现象和原因通常是对应的:首字慢多是加载与预处理问题,持续输出慢多半是内存带宽或算子支持问题。两类现象对应完全不同的动作,先按现象分类再动手,能省很多试错。
想拿一个客观的延迟基线,可以用站内的测速工具跑一遍,把结果记下来当作后续改动的对照组。推荐路径见文末。
打包上机:权重、运行时、版本怎么一起交付
端侧交付物是三件套:权重文件、运行时可执行体或库、一份记录版本与参数的配置清单。缺任何一项,后面出问题都很难复现,尤其是配置清单,很多人觉得可有可无,等到线上表现和测试机不一致时才想起要它。
| 交付物 | 必须记录的内容 | 验证方式 |
|---|---|---|
| 权重文件 | 来源、量化档位、转换脚本版本 | 用配置清单重跑一次转换,结果一致 |
| 运行时 | 版本、编译参数、目标架构 | 在最低配机型上冷启动一次 |
| 配置清单 | 输入尺寸、上下文长度、线程数 | 按清单在另一台机器上复现延迟 |
权重转换与合并要在构建流水线里完成,不要留到设备上做,设备端只做加载。设备上做转换意味着每次启动都要花时间,还可能因为内存峰值直接失败。
不同芯片与系统要分别验证,至少要覆盖目标机型清单里的最低配那一档。回归清单建议固定为:内存峰值、冷启动时间、首字延迟、稳定输出速度、断网可用性、连续运行后的稳定性,每项都设阈值,不达标就不发版。
上线之后:端侧问题的定位套路
端侧没有日志系统就得自己埋。至少要记三类事件:加载失败、内存告警、超时。很多人只记崩溃,但崩溃只是最末端的表现,前面那三类事件才是能定位原因的信息。
- 加载失败:带上权重版本和运行时版本,判断是资源问题还是文件损坏
- 内存告警:记峰值和当时的输入长度,用来反推是哪类请求打爆的
- 超时:记是首字超时还是整体超时,两者指向完全不同的问题
- 机型与系统版本:所有事件都要带,不然没法横向比较
同类机型才能横向比。芯片、系统版本、后台占用不同,速度差异可能远大于模型差异,拿一台低端机和一台旗舰机对比得出的结论基本没有参考价值。
效果不满意时先分清是模型能力问题还是部署问题。判断方法:换一个同尺寸的其他权重,如果明显变好,那多半是原来的量化档位或运行时配置有问题,而不是模型本身不够聪明。这个排查顺序能避免一上来就换更大的模型。
一份可以直接抄的验收清单
把前面几节的动作收进一张清单,每一项都要有记录、有阈值、有责任人。清单本身不是目的,目的是让下一次部署不用从头想一遍。
| 清单项 | 内容 | 验收方式 |
|---|---|---|
| 约束表 | 延迟上限、内存上限、体积上限、离线要求 | 四项齐全,缺一不可 |
| 选型表 | 候选权重、量化档位、运行时、许可类型、加速器支持 | 不合格项已划掉并写明原因 |
| 测试集 | 覆盖真实输入分布,含边界样本与最长输入 | 跑通且结果留档 |
| 指标记录 | 内存峰值、冷启动、首字延迟、稳定速度、连续运行稳定性 | 每项都有阈值和实测值 |
| 回退方案 | 上一版权重与运行时文件留存 | 写清触发回滚的条件 |
清单里最容易被跳过的是测试集和回退方案。测试集不做,等于每轮改动都在盲猜;回退方案不写,等于一次更新赌上整批设备。这两项花的力气不多,但出事时就是它们救场。
端侧部署的核心不是把模型压到最小,而是把每一项约束都变成可测的数字,然后照着数字做取舍。下一步把自己的延迟基线先测出来,再去对照站内同类配置的记录,看看差距在哪一项;顺便翻一下工具目录里的打包与测速工具,能省掉不少自己造轮子的时间。具体数字请到站内页面看当时的结果。→
常见问题
端侧部署一定要量化吗?
不一定,但多数设备的内存与带宽都不够跑原始精度。判断方法是先用原始精度试一次,量出内存峰值和速度,如果离你的硬指标有明显差距,再往下压档位。判别类任务容忍度更高,开放生成类要留余量,最终以你自己真实输入的输出差异为准。
模型在电脑上跑得好好的,为什么到设备上就崩?
最常见是三个原因:内存预算只算了权重,没算上下文缓存和框架开销;加速器没有被真正调用,实际跑了 CPU 路径;权重格式与目标运行时版本不匹配。建议按「内存峰值 → 加速器是否生效 → 格式与版本」的顺序排查,而不是先怀疑模型本身。
端侧该选多大的模型?
没有通用答案,先看你设备的内存上限,再倒推能塞下的参数量与量化档位,然后在这个范围内挑候选。判别、抽取这类任务小模型往往够用;开放生成需要更大余量。拿不准就到站内模型库和部署测算页面,按同类配置的实际报告对一遍再定。
怎么判断瓶颈在模型还是在部署?
换一个同尺寸、同量化档位的另一个权重,如果速度或效果明显变化,多半是部署配置问题而不是模型能力上限。另外把冷启动、首字延迟、稳定输出速度分开测,首字慢通常是加载与预处理,持续慢多半是带宽或算子,方向完全不同。
端侧部署和直接调接口怎么取舍?
涉及数据不出设备、必须离线、或者调用量极大摊不平成本时,端侧更合适。反之,如果模型需要频繁更新、效果要求接近云端大模型、团队没有打包与版本管理能力,调接口的总体成本更低。两条路的分界线可以参考站内关于自建与调用的那几篇。