输入、输出与并发如何共同影响服务
一句话收获:性能判断必须同时说明输入、输出、并发、模型和硬件条件。
这个场景在解决什么问题
这个场景要建立几个关键概念的直觉:Token(模型处理文本的最小单位,可以粗略理解成一个字/词片段)、上下文窗口(模型一次能"看到"的最大范围)、Prefill(预填充,读取并编码输入阶段)、Decode(解码,逐字生成输出阶段)、并发。
观察方式是"固定模型,只改变输入长度、输出长度和并发"——控制变量,看每个变量单独变化时性能怎么变。它的价值在于:以后别人说"这个接口很快/很慢",你能立刻反应过来"他缺了条件,这话没意义"。
先理清这条判断链(文字版)
判断一次模型服务的性能,按这条链把变量都盯住:
- 先看输入变长:输入越长,首字等待是不是先变长?(第 1 步:输入变长)
- 再看输出变长:首字出来了,但完整结果是不是还得慢慢生成?(第 2 步:输出变长)
- 再看并发增加:多份上下文同时占缓存、进调度,请求是不是开始排队?(第 3 步:并发增加)
- 最后做完整判断:有没有同时记录输入、输出、并发、首字、总耗时、结束原因和质量?(第 4 步:完整判断)
一句话串起来:先看输入影响首字 → 再看输出影响总时长 → 再看并发影响排队 → 最后把所有条件一起记录才能下结论。缺任何一个条件,性能数字都没法比。
逐层详解
第 1 步:输入变长
原文:模型读取更多材料,首字等待通常先增加。
白话:输入(Prompt)越长,模型要先"读"的材料越多,所以"从发出请求到吐出第一个字"的等待时间通常先变长。这阶段叫 Prefill,负责读取和编码当前输入。
类比:Prefill 是"阅读题干"阶段——考试时题目越长,你读完题、下笔写第一个字之前,花的时间就越长。
举例:同一个模型,给它 100 个 Token 的输入和 10000 个 Token 的输入,后者的首字等待明显更久,因为 Prefill 要把这一大段全部读进来、编码完,才能开始生成第一个字。
为什么重要:Prefill 负责读取和编码当前输入——它决定了"首字之前要等多久"。
怎么验证(证据点):
- 输入 Token 增加
- 首字等待增加
- 模型不变
别踩的坑(边界):上下文装得下不证明每条要求都能正确使用——材料塞得进去,不代表模型每条都真的读懂了、用上了。
落地检查:长输入主要先影响读取阶段——看到长输入慢,先看是不是卡在 Prefill(首字等待),而不是生成阶段。
第 2 步:输出变长
原文:首字已经出现,但完整结果仍需逐步生成。
白话:首字出来了,不代表完事。输出越长,模型要一个 Token 一个 Token 地"吐",这阶段叫 Decode。所以总耗时里,很大一块是"生成"的时长。
类比:Decode 是"逐字写答案"阶段——读完题写了第一个字,但整篇答案还得一个字一个字写,写得多就久。
举例:让模型生成 10 个字和生成 1000 个字,首字时间差不多,但后者的总耗时长得多,因为 Decode 阶段要逐 Token 生成,生成越多越慢。
为什么重要:Decode 负责逐 Token 生成输出——它决定了"完整结果要多久"。
怎么验证(证据点):
- 输出 Token 增加
- 生成时间增加
- 结束原因可查
别踩的坑(边界):首字快不等于完整结果快——首字秒回,但完整结果可能要等很久,别只看首字就下结论。
落地检查:首字等待和生成耗时是两个指标——把"首字时间"和"生成总时长"分开记录,别混成一个数字。
第 3 步:并发增加
原文:多份上下文同时占用缓存并进入调度,请求开始排队。
白话:并发(同时处理的请求数)一上来,每个请求都要占显存里的缓存(KV cache),又要进调度器排队,于是缓存压力和排队同时出现。
类比:并发是"同时来了多少个客人"——每个客人都占一个工位(缓存),还要排队等厨师(调度)。客人一多,工位不够、队伍变长。
举例:推理服务并发从 1 涨到 32,每个请求的 KV 缓存叠加把显存吃满,后面来的请求全部排队等前面的算完,整体延迟被拉高。
为什么重要:并发同时影响显存、缓存、批处理和队列——它是个"牵一发动全身"的变量。
怎么验证(证据点):
- 并发上升
- 缓存压力上升
- 排队出现
别踩的坑(边界):增加设备不能自动修复无效长上下文——靠加卡解决并发,但无效的长上下文还在白白占缓存,加卡只是掩盖问题。
落地检查:并发问题要同时检查容量和调度——既要看缓存容量够不够,也要看调度策略合不合理,两个都要查。
第 4 步:完整判断
原文:同时记录输入、输出、并发、首字、总耗时、结束原因和质量。
白话:要下性能结论,必须把这几个变量和指标一起记录:输入长度、输出长度、并发、首字时间、总耗时、结束原因(正常结束还是超时/错误)、生成质量。缺一个,结论就站不住。
类比:性能结论像一份完整的体检报告——只写"心跳 60"没用,得把血压、血糖、体重、年龄一起写,医生才能判断健康不健康。
举例:一份靠谱的性能测试报告会写"输入 2000 Token、输出 500 Token、并发 16、首字 0.8s、总耗时 12s、正常结束、质量无退化",这样别人才能复现和比较。
为什么重要:只有控制变量明确,优化结果才可解释——不写条件的"快/慢",等于没测。
怎么验证(证据点):
- 条件完整
- 指标分层
- 质量未丢失
别踩的坑(边界):单一速度数字不能跨环境比较——"每秒 30 Token"这句话,换个输入长度、换个并发、换块卡,就完全没可比性。
落地检查:性能结论必须带运行条件——报性能时,把输入、输出、并发、模型、硬件条件一起写清楚。
落地可行性小结
本场景涉及的技术栈:Token、上下文窗口、Prefill、Decode、并发、KV 缓存、推理服务调度。
真实落地怎么做:做性能测试时,固定模型和硬件,分别只改输入长度、输出长度、并发三个变量,分别记录首字时间、总耗时、结束原因和质量。
要检查什么:首字等待和生成耗时是否分开记录、结束原因是否可查、并发时缓存和队列是否都观察了、质量有没有在优化中丢失。
常见坑:只看首字就下结论;把"首字时间"和"总耗时"混成一个数;报性能不带条件;加卡掩盖无效长上下文的问题。
回顾
- 性能判断必须带条件:输入、输出、并发、模型、硬件,缺一不可。
- Prefill 管输入编码,决定首字等待;Decode 管逐字生成,决定总耗时。
- 首字快 ≠ 完整结果快,两个指标要分开看。
- 并发同时压显存、缓存、批处理和队列,要一起检查容量和调度。
- 单一速度数字不能跨环境比较,报性能必须带运行条件。