跑分数字不等于稳定部署:从全精度、量化到性能实测 DeepSeek V4 Flash278 tok/s全精度无量化。这行字放在一起差不多是跑过本地模型的人最爱看的组合数字够大速度够猛而且听起来没有用质量换速度。看到这种标题很多人第一反应是赶紧去查自己的显卡能不能也跑出这个数。但如果你真的把模型搬进过项目用过一段时间就会意识到一个跑分数字要成立条件其实非常苛刻任务要匹配硬件要匹配环境要稳定而且同样条件下要能再次跑出来。我更愿意把这句话拆成三个信息来看tok/s 是速度决定交互体感全精度是权重存储方式决定输出质量和显存占用无量化是后缀说明这个速度不是靠压缩模型换来的。方向听上去很理想但到了自己的机器上能不能复现、需不需要复现才是真正的工程问题。这篇文章想说的结论很朴素跑分是起点不是终点单次跑通不等于能稳定批量使用全精度、无量化、高吞吐这些卖点能不能成为你的默认配置要由任务风险、硬件预算和维护成本共同决定而不是由标题里的数字决定。1. 拆开标题278 tok/s、全精度、无量化每个词都对应一个代价一个标题越简洁越容易让人忽略里面其实藏着三个独立的工程决策。先把每个词拆开看。1.1 先搞清楚 tok/s 在衡量什么token 是模型处理文本的最小单位英文里一个词经常分成一到两个 token中文里一个汉字通常对应一到两个 token。所以 278 tok/s 换算成可感知的速度大约相当于每秒输出两三百个汉字。这个速度放在交互场景里非常快你几乎感觉不到等待输出这个过程更像是看一个人在屏幕上快速打字。但这里有个容易混淆的点tok/s 是生成速度不是响应时间。响应时间里还包含排队时间、输入处理时间、首 token 延迟。一个系统可以首 token 很慢但后续生成飞快平均 tok/s 依然很好看。反过来也可能单条请求很快一旦并发上来速度立刻塌下去。所以在兴奋之前先问自己三个问题这个 278 tok/s 是单条请求测出来的还是并发压力下测出来的是稳定值还是峰值测的时候上下文有多长、生成了多少个 token这三个问题的答案决定了这个数字对你的参考价值是 80% 还是 20%。1.2 全精度模型用原声说话但显存和成本要跟上全精度不是指某一个固定格式而是相对量化而言的说法。模型权重可以按不同的数值格式存储常见的有 FP32、FP16、BF16以及量化后的 INT8、INT4。下面的表可以帮你快速建立换算关系存储格式每参数占用相对 FP32 体积典型用途需要留意的点FP324 字节100%训练、数值敏感调试显存占用最高推理很少用FP162 字节50%常见推理格式数值范围有限大模型偶尔溢出BF162 字节50%大模型训练/推理主流精度位数少但范围大问题少INT81 字节25%性价比推理需要校准极端值可能丢精度INT40.5 字节12.5%消费级显卡跑大模型质量损失最大必须实测全精度推理一般指用 FP16 或 BF16 这类不压缩的格式跑完整权重。好处是模型行为和训练时最接近数值误差小输出更稳定尤其是数学、代码、长上下文抽取这类对细节敏感的任务。代价也很直接显存占用是 INT4 的四到八倍。一个在量化下装得进 24GB 显卡的模型换成全精度可能就需要 32GB 甚至更高再加上 KV cache 和运行开销实际需求还会再往上走。1.3 无量化不一定是你的最优解无量化意味着模型权重没有经过压缩推理结果更接近原始行为。这当然是一个优点但不是免费的。它要求你有足够大的显存还要能承受相应成本。对一个跑在个人电脑上的实验项目量化几乎是必须的对一个跑在数据中心里、有明确吞吐指标的生产任务全精度可能又是值得的。这里的关键不是量化好还是全精度好而是你的硬件和任务能不能支撑你选择全精度。标题里的组合只说明一件事有人在一套特定硬件上用全精度跑出了这个速度。它没有说明这套硬件是什么、成本多少、稳定性如何。而这些恰恰是决定你能不能照搬的关键。注意任何没有注明硬件、上下文长度、并发和输出长度的 tok/s 数字都不应该直接作为你的选型依据。2. 峰值跑分和真实部署之间至少隔着三层测试我自己在验证一个性能主张时从来不会拿标题里的数字直接开始调参。我会按三层测试一步步来每一层都只回答一个问题。2.1 第一层测试单请求复现把所有变量压到最小先关闭一切干扰因素用一条最短的有效输入去确认三件事模型能不能正常加载、请求能不能走通、输出的 tok/s 和你看到的宣传值差多少。常见做法是起一个 OpenAI 兼容的服务接口然后用一条 curl 或 Python 请求去测。下面是常见的测法结构# 单请求耗时与输出 token 数估算 time curl -s http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: your-model-id, messages: [{role: user, content: 写一段 200 字的活动通知}], max_tokens: 512, temperature: 0.7 }这个阶段不要急着调并发和量化。先把服务跑通记录下最基础的三个数据首 token 延迟、平均生成速度、输出是否完整。如果单条请求的 tok/s 就和宣传值差出一个量级后面就不用比了先排查硬件、驱动、模型路径和上下文长度。2.2 第二层测试并发和资源竞争模拟有人和你抢单条速度快不代表并发下速度快。真实系统里模型服务往往是多人在用的办公场景有人在问问题有人在生成代码还有人可能在跑批量摘要。并发一上来GPU 利用率升高显存带宽被争抢tok/s 会出现明显下降。我在这一层通常用一个小脚本循环发请求记录每次请求的耗时和输出 token 数然后把分布统计出来import time import requests url http://127.0.0.1:8000/v1/chat/completions payload { model: your-model-id, messages: [{role: user, content: 解释一下什么是全精度推理}], max_tokens: 256, temperature: 0.3, } for i in range(20): start time.time() resp requests.post(url, jsonpayload, timeout60) cost time.time() - start output_tokens resp.json().get(usage, {}).get(completion_tokens, 0) print(f第 {i1} 次耗时 {cost:.2f}s生成 {output_tokens} tokens约 {output_tokens / cost:.1f} tok/s)注意这个脚本只是先做单请求串联真正的并发测试还需要用线程、协程或多进程同时发请求并统计 P50、P95 延迟。为什么强调 P95因为平均延迟会被少数慢请求拉平而 P95 反映的是大部分用户在较差情况下的体验。如果 P95 是平均值的两倍以上说明系统在并发下很不稳定。2.3 第三层测试长跑稳定性跑半小时后再看速度最容易忽略的一层是长时间运行。模型服务刚启动时性能通常会好一些因为各种缓存是冷的显存布局也更规整。运行一段时间后可能出现显存碎片、KV cache 增长、连接句柄耗尽、缓存命中率下降等问题速度会悄悄变慢。我一般会让服务持续跑 30 到 60 分钟中间持续打请求每 5 分钟记录一次平均 tok/s。如果前 10 分钟和最后 10 分钟的差距在 10%-20% 以上就要去看资源监控显存占用有没有持续上涨、GPU 利用率是不是在掉、是不是有什么后台任务在抢资源。长期服务里稳定速度比峰值速度重要得多。提醒不要一上来就把并发和 max_tokens 拉满。先让一条样本完整跑通再逐步加压否则你很难判断慢是模型的问题、显存的问题还是并发设计的问题。3. 量化不是敌人全精度与否应该由任务风险决定把无量化当成天然优点是很多性能标题给人留下的错觉。量化本质上是用可接受的精度损失换取显存、速度和成本的改善。它不一定要损失到你肉眼可见关键在于你的任务对误差有多敏感。3.1 量化到底省了什么又付出了什么量化省下的是三样东西显存、带宽、成本。显存小了小显卡能跑更大的模型带宽占用小了每 token 生成速度可能更快成本低了同样的预算能服务更多用户。付出的则是数值精度。INT8 和 INT4 会把权重从高精度空间映射到低精度空间模型学到的细微差别可能被磨平。大多数通用对话里这个问题不明显但在需要精确计算、严格逻辑、逐字抽取的场景误差会被放大而且通常不是简单地多错一两个字而是可能在关键步骤上出错。3.2 按任务风险选择精度等级我判断要不要用量化的依据不是量化好不好而是这个任务出错成本高不高。下面这张表是我常用的分类方式任务类型典型特征建议实时对话、闲聊对单次表达不敏感中低量化通常够用代码生成、程序修复逻辑正确性要求高优先全精度或轻度量化数学、逻辑推理步骤和数值敏感优先全精度长文档摘要、信息抽取完整性要求高漏一点可能就是大问题先全精度跑基准再决定批量结构化输出格式稳定性要求高全精度和量化各跑一轮对比这套判断逻辑的核心是先定义什么算不可接受的错误再决定精度。如果任务是给文章起标题量化带来的误差完全可以接受如果是抽取合同里的金额和日期一个小数点的错误可能比慢 30% 严重得多。3.3 一张可以直接抄走的决策表实操时我一般按四步走用全精度在目标硬件上跑一遍代表性任务记录质量和速度。用候选量化级别跑同一批任务记录质量差异。如果质量差异在可接受范围内再比较速度、显存和成本。如果质量差异超出容忍线直接放弃量化哪怕速度不理想。不要跳步。很多人一上来就选 INT4理由只是小一点、快一点结果上线后才发现抽取类任务错了太多返工成本早就超过了省下的那点算力钱。量化是一件需要按任务验证的事不是一个可以提前拍板的全局决策。4. 跨模型对比的正确姿势同一把尺子量所有模型glm-5.3-flash 和 deepseek v4 flash 对比这类问题现在很常见尤其是定位相似的轻量快模型越来越多。但绝大多数对比帖子都犯了一个同样的错误在不同的条件下测出了两个数字然后用这两个数字下结论。4.1 固定变量才能对比变量速度和质量的对比只有在变量可控时才有意义。下面这份清单是我做对比前必查的要固定的变量为什么重要硬件与驱动不同显卡的速度差可达数倍模型格式全精度对比全精度量化对比量化上下文输入长度输入越长单位时间吞吐可能越低输出长度上限max_tokens 不同平均速度会失衡并发数单条和并发是两种完全不同的指标采样参数temperature、top_p 不同生成长度差异大评测集必须同一批问题、同一评分标准服务状态冷启动和预热后性能差异明显很多对比贴上来的数字硬件、量化、上下文长度全都不一样那不是在对比模型是在对比运气。4.2 别只看平均速度要看延迟分布和失败率跨模型对比时我至少看四个指标平均 tok/s、P50 延迟、P95 延迟、失败率。平均速度高但 P95 延迟飘忽的模型交互体验反而差失败率高的模型更危险因为它带来的不是变慢而是任务中断。这里还要区分生成速度和端到端耗时。有的服务把输入处理、排队、网络传输都算进去端到端自然慢有的只统计生成阶段数字当然好看。对比前先确认统计口径否则就是在拿苹果比橘子。4.3 质量评测要单独做不能靠体感速度能复现但质量要评测。体感好像差不多在工程上不算证据。如果你的任务有明确答案是代码、数学题、结构化输出直接拿同一批样例跑按正确率打分。如果任务是开放性写作至少也要抽出几个维度比如信息完整性、逻辑连贯性、格式稳定性由同一评分标准来评。匹配自己任务的评测比任何公开榜单都重要。榜单面向的是通用场景而你的场景是具体的。5. 参数设置先跑通、再优化、最后批量化关于DeepSeek V4 Flash 参数设置网上能搜到很多别人分享的配置。我的建议是别人给的参数可以当起点但不要当结论。参数这东西高度依赖任务、硬件和预期输出照抄一份未必适合你。5.1 第一轮最小可用配置先让流程完整第一轮的目标不是效果好而是流程通。用默认参数、一条输入、一个明确输出确认服务能正常返回日志没有异常输出结构符合预期。常见推理服务框架的启动参数大致长这样具体以你实际使用的框架为准# 常见开源推理服务框架的启动参数示例 python -m vllm.entrypoints.openai.api_server \ --model /data/models/deepseek-v4-flash \ --dtype bfloat16 \ --max-model-len 8192 \ --max-num-seqs 8 \ --port 8000模型路径和模型 ID 以你实际部署为准这里只是展示一个可执行结构。先不追求效果把服务拉起来用一条最短请求确认链路完整。这一步跑不通后面所有调参都是空中楼阁。5.2 第二轮单点调参一次只动一个旋钮很多人调参喜欢同时改好几个参数最后出了问题完全不知道是谁引起的。正确的做法是一次只动一个变量改完跑完记录完再动下一个。几个常见参数的作用要先分清楚temperature控制随机性值越大越发散代码和抽取任务通常用更小的值。top_p控制候选词范围和 temperature 有相关性一般先固定一个再调另一个。max_tokens控制输出长度上限设得太短会截断设得太长会浪费等待时间。batch size / max_num_seqs控制并发吞吐越大越吃显存。上下文长度越长占用的 KV cache 越多直接影响可支撑的并发数。这里的常见经验值是开放对话 temperature 可以放在 0.7 到 0.9代码、抽取、数学任务放在 0.1 到 0.3结构化输出还要配合格式约束单纯调温度解决不了格式问题。这些是通用经验不是某个模型的官方结论具体值要按你的任务实验。5.3 第三轮批量化之前先补日志、重试和限流当你确认参数没问题想从单条任务扩展到批量任务时真正的工程问题才出现失败怎么重试、超时怎么处理、并发怎么控制、日志怎么记录。我见过最典型的翻车方式是直接写了一个 for 循环把几百条任务一次性发出去结果一半请求超时输出文件里混着成功和失败最后还得重新跑一遍。批量任务一定要把下面几件事提前做好每一条任务都有唯一 ID方便追踪。请求失败自动重试但要有上限和退避策略。并发数从 1 慢慢往上加观察显存和延迟变化。输出结果落盘时标记每条成功或失败。保留请求参数和模型版本出了问题能复现。这些都是繁琐但必要的工作。它们不直接提升速度但它们决定了这个方案能不能长期用下去。6. 落进工程之前先把这条排查链路刻进脑子最后说排查。无论是速度慢、报错还是输出异常我用的一直是同一套排查顺序。它不一定最快但一定不会让你在错误的方向上浪费时间。6.1 一张排查顺序表输入、环境、参数、资源、工具边界排查层级看什么现象是报错、卡住、无输出、输出乱还是慢输入格式、编码、长度、路径、消息结构是否正常环境依赖版本、驱动、权限、端口是否冲突参数上下文长度、max_tokens、并发、温度是否合理资源显存占用、GPU 利用率、内存、磁盘、网络带宽工具边界版本兼容、功能限制、当前场景是否超出工具能力顺序很重要先确认是完全不可用还是可用但不快再去看输入和环境。很多人一报错就去看 GPU 驱动结果问题只是请求体里少了一个字段。6.2 三类最常见问题的处理思路第一类是速度远低于预期。优先确认三件事模型是不是发生了显存换入换出、上下文是不是比想象的长、是不是在冷启动状态。如果是显存不够最常见的解法是缩短上下文、降低并发或者换更激进的量化但这个取舍要回到第三章节的任务风险判断。第二类是输出乱码或截断。先看 max_tokens 是否够用再看输入的编码和格式最后看量化格式是否过猛。乱码和截断经常被误判成模型能力问题实际上是参数或预处理问题。第三类是请求超时或报错。优先查模型 ID、路径、权限和并发限制再用最小请求去排除服务本身的可用性。服务端日志通常是第一手信息比猜测快得多。6.3 回到那个最朴素的主判断绕了一大圈我想说的还是开头那句话278 tok/s 是一个让人兴奋的数字全精度和无量化是有分量的定语但真正能让你把方案长期用下去的不是某一个跑分数字而是你在自己的硬件上、自己的任务里验证过、测试过、还能稳定复现的那一组结果。先验证再兴奋。先建立基准再谈优化。先补好日志和重试再考虑批量。这一套流程听起来不像标题那么热血但它才是工程里真正稀缺的部分。