LLM推理速度指标解析:从TPS到vLLM部署优化实践 📅 发布时间:2026/8/30 16:06:55 👁 浏览次数: Celeris-1 以 2158 tokens/s 的生成速度登顶 AI 速度排名这组数字迅速成为模型推理讨论里的一个参照点。很多人看到这个数据后的第一反应是每秒 2158 个 token按中文文本估算已经是每分钟十几万字这个速度到底是怎么测出来的它能不能直接等价于用户聊天时感知到的快慢如果自己手头也有一张 GPU能否用同样口径复现或接近这个结果这些问题比“谁排第一”更值得展开。下面的内容会从速度指标的定义开始逐步拆解一次模型推理速度测评需要哪些条件以及从“测出 2158 tokens/s”到“在生产环境稳定提供服务”之间还存在哪些工作。内容偏向 LLM 应用集成、模型部署和性能调优的开发者。读完应该能自己设计一份可复现的测速方案也能在服务上线后定位推理变慢的常见原因。1. 先搞清楚 tokens/s 衡量的是哪一种速度1.1 从聊天体验理解 TTFT、TPS、TPOT用户在对话框里发出请求后不会立刻看到完整答案。浏览器或客户端会先等待模型返回第一个 token然后后面的内容才像“打字机”一样逐步出现。这两段体验分别对应两种不同性质的指标TTFTTime To First Token从请求发出到收到第一个 token 的时间单位通常是毫秒或秒。TPOTTime Per Output Token生成每个输出 token 的平均耗时单位通常是毫秒。TPSTokens Per Second每秒生成的 token 数量和 TPOT 成反比表达式是TPS 1000 / TPOT。端到端延迟从请求发出到最后一个 token 返回的总耗时等于 TTFT 加生成阶段总耗时。用 2158 tokens/s 这个例子来换算TPOT 1000 / 2158 ≈ 0.463 毫秒也就是平均每个输出 token 只要 0.463 毫秒。这个数值说明在对应测试条件下解码阶段的显存带宽和算子优化都已经做到很高的水平。指标单位衡量内容用户感知TTFT毫秒或秒首 token 返回快慢是否感觉“开始回答”很慢TPOT毫秒每个输出 token 的耗时打字机速度TPStokens/s每秒输出 token 数整体生成快慢端到端延迟秒完整回答耗时从提问到回答完毕这里要特别注意通常讨论“生成速度”时指的都是解码阶段也就是模型已经读完用户输入、开始逐 token 输出的阶段。模型接收 prompt 并预计算中间状态的阶段叫 prefill它的耗时用另外的方式评估。速度排名里的 TPS 数字绝大多数时候只代表 decode 速度不代表用户在真实对话里感受到的完整响应时间。1.2 为什么同一个模型不同团队测出的 TPS 经常对不上模型推理速度并不像 CPU 主频那样是一个相对固定的物理参数。同一个模型用不同硬件、不同精度、不同推理引擎、不同并发数测出来的 TPS 可能相差数倍。Celeris-1 的 2158 tokens/s 是“在特定测试条件下”的结果如果脱离条件直接和其他模型比较很容易得出错误结论。至少这些因素会影响 TPS 的最终数值影响因子说明权重精度FP16、BF16、INT8、INT4 的显存带宽需求和算子速度不同GPU 型号显存带宽、算力、显存容量都会直接影响 decode 速度推理引擎vLLM、TensorRT-LLM、SGLang、llama.cpp 的调度和算子优化差异明显并发数单路请求和多路并发时的 TPS 含义完全不同输入长度长 prompt 会增加 prefill 耗时也会影响 KV Cache 占用输出长度输出越长统计窗口里的平均值越能反映真实 decode 速度KV Cache 命中状态是否命中 prompt cache 会显著改变耗时请求协议OpenAI 兼容接口、原生 gRPC、流式与非流式都有额外开销所以看到 2158 tokens/s 这样的数据时不要急着认定“这就是模型本身的速度”。它只是一份测试报告里的结果必须同时确认测试环境、精度、解码策略和并发设置才能判断它是否可以复现。1.3 单流速度、并发吞吐和用户体感不是一回事速度排名更多是在“单流请求”或“低并发”环境下测出来的但生产环境里几乎是多用户同时请求。这里的区别很关键单流 TPS只有一个请求在推理引擎里运行模型独占 GPU 的显存带宽速度往往最高。系统吞吐多个请求并发时推理引擎通过动态批处理同时处理多条序列每秒输出的总 token 数会上升但每一条请求的平均 TPS 通常会下降。用户体感速度除了生成速度还要看 TTFT、网络延迟、排队时间、流式返回的稳定性。换句话说一个服务如果只关注单流 TPS可能会得到“很快”的结论但一旦把并发用户加进来平均每条请求的生成速度可能从 2158 掉到 800 甚至更低。生产容量规划必须使用“并发场景下的吞吐”和“延迟分位数”而不是排行榜里的峰值 TPS。注意不要只验证服务能启动还要确认测速数字的测量口径。否则排行榜上的 2158 tokens/s 和生产环境的实际体验可能差出好几倍。2. 复现或验证速度数据测评流程怎么设计2.1 最小测评环境先固定一个能跑通的起点如果要验证一个开源模型的推理速度不建议直接拿生产环境的大集群压测。更稳妥的做法是先固定一套最小可复现的环境。这里以常见的大模型推理场景为例说明需要哪些条件。实际落地时请按自己使用的模型、框架版本和显卡型号调整。依赖项说明示例GPU显存需要能容纳模型权重、KV Cache 和推理引擎开销24GB 或 80GB 显存的 NVIDIA 显卡CUDA推理框架依赖 CUDA 运行时和 cuBLAS 等库CUDA 12.xPython推理框架大多通过 Python 调用Python 3.10 或 3.11推理引擎负责模型加载、批处理、算子调度vLLM、SGLang、llama.cpp模型权重模型权重文件和对应 tokenizerHugging Face 格式或 GGUF 格式测速脚本发送请求并统计时间与 token 数Python 脚本或官方 benchmark 工具一个很常见的起步组合是单张 NVIDIA A100 或 RTX 4090配合 vLLM加载一个已量化的开源模型。这个组合能跑通最小闭环也最容易暴露显存不足、依赖冲突和参数配置错误。2.2 用 Python 脚本测量实时生成速度先不用复杂压测工具可以直接写一个最简单脚本通过 OpenAI 兼容接口请求模型统计流式返回的 token 数和耗时。下面脚本用于说明测速思路实际项目要结合自己的服务地址、模型名和 API Key 调整。import json import time from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000/v1, api_keyEMPTY, ) prompt 用 300 字介绍什么是模型推理优化。 messages [ {role: user, content: prompt}, ] start time.time() response client.chat.completions.create( modelyour-model-name, messagesmessages, streamTrue, ) output_tokens 0 first_token_time None for chunk in response: delta chunk.choices[0].delta if delta and delta.content: if first_token_time is None: first_token_time time.time() output_tokens len(delta.content) end time.time() ttft first_token_time - start total_time end - start tps output_tokens / (total_time - ttft) if output_tokens 0 else 0 print(TTFT: {:.2f}s.format(ttft)) print(total_time: {:.2f}s.format(total_time)) print(output_tokens: {}.format(output_tokens)) print(TPS: {:.2f}.format(tps))这个脚本把首 token 到达时间单独记录生成阶段才参与 TPS 计算口径比较接近排行榜里的 decode 速度。运行时需要注意两个细节这里用len(content)统计 token 数对中文字符不够准确。如果要更精确应该从响应里的usage字段取completion_tokens或者使用 tokenizer 统计实际 token 数。本地服务距离远不远、是否走流式都会影响 TTFT但不应该显著影响生成阶段的 TPS。如果两者都慢需要分别排查网络和服务端。2.3 用 vLLM 的 benchmark 脚本做标准化压测手写脚本适合验证单次请求流程但要做多参数对比更推荐用推理引擎自带的 benchmark 工具。vLLM 提供benchmark_throughput脚本可以一次测试多个请求的吞吐。python -m vllm.benchmark.benchmark_throughput \ --model /path/to/model \ --tensor-parallel-size 1 \ --input-len 128 \ --output-len 256 \ --num-prompts 20 \ --max-num-seqs 8 \ --seed 42参数含义参数作用--model模型路径或 Hugging Face 模型名--tensor-parallel-size使用几张 GPU 做张量并行--input-len构造 prompt 时的输入 token 长度--output-len期望生成的 token 长度--num-prompts发送的总请求数--max-num-seqs推理引擎同时处理的最大序列数--seed随机种子固定后结果可复现脚本运行结束后会输出吞吐率单位通常是requests/s和tokens/s。这个tokens/s是所有请求共享的总吞吐写报告时要和单流 TPS 区分清楚。2.4 一份可复现的测速报告至少包含哪些字段如果要把测速数据放进技术文档或对比报告中至少需要记录以下字段否则别人无法复现字段示例模型名称与版本Qwen2.5-7B具体 commit 或 revision权重精度FP16 / INT8 / INT4推理引擎及版本vLLM 0.8.xGPU 型号与数量NVIDIA A100 80G x 1并发请求数1、8、32输入 token 数128输出 token 数256TTFT 分位数p50 120msp95 180msTPS 或吞吐单流 2158并发 32 时总吞吐 4200KV Cache 是否开启prefix caching on/off只有把这些条件都写清楚2158 tokens/s 这样的数据才有比较价值。3. 决定 token 生成速度的五个关键因素3.1 模型规模与权重精度显存带宽是主要瓶颈解码阶段每生成一个 token都要把模型所有权重从显存读取一次。因此 decode 速度的上限很大程度上受显存带宽约束而不是单纯受 GPU 算力约束。模型参数越多需要读取的权重数据就越大生成单 token 的理论最短耗时也会变长。权重精度又直接决定需要读取的数据量精度单参数占用7B 模型权重体积速度潜力质量风险FP16/BF162 字节约 14GB基准低FP81 字节约 7GB可能提升需评测INT81 字节约 7GB可能提升需评测INT4/FP40.5 字节约 3.5GB提升明显较高需验证输出质量量化不是免费的。把 FP16 降到 INT4TPS 常常能翻倍但也可能让输出质量下降、推理结果不稳定。正确的做法是先在评测集上对比量化前后的输出质量再决定是否上线。3.2 推理引擎与算子优化同一模型在不同引擎里速度差异很大当前主流推理引擎都做了大量算子融合、显存复用和调度优化选择不同引擎TPS 可能差出 20% 到 100% 甚至更多。推理引擎核心优化手段适合场景vLLMPagedAttention、Continuous Batching高并发在线服务TensorRT-LLM算子融合、图优化、量化 kernelGPU 上追求极致吞吐SGLangRadixAttention、结构化接口优化复杂 prompt 复用和多轮对话llama.cppCPU/GPU 混合、GGUF 量化本地轻量部署、边缘环境这里不需要一开始就选出“最强引擎”而是要明白任何 TPS 数据都必须带上引擎名称和版本。同一个模型从 vLLM 0.5 升级到 0.8速度可能都有明显变化。3.3 KV Cache 与输入长度长上下文会挤压并发空间每次解码时模型会把历史 token 的 Key 和 Value 缓存到显存中这部分空间就是 KV Cache。输入越长、batch 越大KV Cache 占用越高。当显存不足以容纳更多缓存时推理引擎必须限制并发或减少 max-model-len从而影响整体吞吐。长输入还会让 prefill 阶段耗时增加。即使 decode 速度不变端到端延迟也会因为 prefill 时间变长而上升。所以测速时不能只测短输入还要覆盖业务里真实存在的长文档场景。3.4 投机解码用小模型草稿大模型验证拉高 TPS投机解码Speculative Decoding的思路是用一个更小、更快的草稿模型先连续生成若干 token再由目标模型一次验证这些 token 是否正确。如果验证通过一次前向计算就能产出多个 token实测 TPS 可以显著提升而且不影响最终生成内容。不过投机解码并不总是有效草稿模型和目标模型的分布越接近接受率越高收益越大。需要额外显存加载草稿模型。在低并发或输出很短时收益可能不明显。部分推理引擎已经内置该功能使用成本较低。如果目标是逼近 2158 tokens/s 这种高速指标投机解码通常是后续优化的重要手段。3.5 动态批处理与并发数单流速度和系统吞吐必须平衡Continuous Batching 会实时把新请求插入正在计算的 batch提高 GPU 利用率。并发数增加时单条请求的 TPS 可能下降但系统总吞吐上升。测速时如果不固定并发数得到的数据几乎没有跨项目可比性。实践中常用max-num-seqs控制推理引擎同时处理的最大序列数。这个参数太小GPU 利用率不足总吞吐偏低太大单条请求延迟变高可能出现排队超时。具体取值需要结合业务延迟目标和 GPU 显存反复测试。4. 用 vLLM 把速度数据变成可复现部署配置4.1 安装环境并确认版本匹配在 GPU 服务器上验证推理速度vLLM 是一个上手较快的选择。安装前先确认 Python 版本、CUDA 版本和 PyTorch 版本兼容。以常见环境为例# 创建虚拟环境 python3.11 -m venv .venv source .venv/bin/activate # 安装 vllm pip install --upgrade pip pip install vllm安装完成后验证版本python -c import vllm; print(vllm.__version__)如果服务器上有多个 CUDA 版本先确认nvidia-smi显示的驱动版本和nvcc版本避免 API 兼容问题导致加载模型失败。这里不给固定版本号因为 vLLM 迭代快落地时以官方发布说明为准。4.2 启动 OpenAI 兼容服务vLLM 提供vllm serve命令可以快速启动一个兼容 OpenAI Chat Completions 接口的服务。vllm serve /path/to/model \ --max-model-len 4096 \ --gpu-memory-utilization 0.9 \ --tensor-parallel-size 1 \ --quantization awq参数说明参数含义注意事项--max-model-len模型支持的最大上下文长度设置过大会增加显存预留设置过小长文档会报错--gpu-memory-utilization允许使用的显存比例0.9 表示最多用 90%要留出空间给推理引擎内部开销--tensor-parallel-size张量并行的 GPU 数量显存不足时提高但要考虑多卡通信开销--quantization量化方式需要与模型权重格式匹配例如 awq、gptq、fp8启动成功后服务会监听http://localhost:8000。这时可以先用 2.2 节的脚本验证请求是否正常返回再进入压测。注意生产环境需要在这层之外考虑鉴权、限流、日志和监控。vLLM 默认的 HTTP 服务更多是给开发验证使用直接暴露内网或公网会有安全风险。4.3 用并发压测脚本模拟多用户请求单条请求验证通过后需要模拟多人同时提问。下面脚本用aiohttp并发请求同一个服务统计总输出 token 数和总吞吐。import asyncio import time import aiohttp BASE_URL http://localhost:8000/v1/chat/completions MODEL your-model-name async def send_one(session, prompt): payload { model: MODEL, messages: [{role: user, content: prompt}], stream: True, } token_count 0 start time.time() async with session.post(BASE_URL, jsonpayload) as resp: async for line in resp.content: if not line: continue text line.decode(utf-8) if text.startswith(data: [DONE]): break if text.startswith(data:): try: # 这里只统计字符数生产环境建议通过 usage 字段统计 token content text.split(data:, 1)[1].strip() if content: token_count 1 except Exception: continue end time.time() return token_count, end - start async def main(): prompts [介绍 Redis 的基本数据结构] * 16 async with aiohttp.ClientSession() as session: start time.time() results await asyncio.gather(*[send_one(session, p) for p in prompts]) end time.time() total_tokens sum(r[0] for r in results) elapsed end - start total_tps total_tokens / elapsed if elapsed 0 else 0 print(total tokens:, total_tokens) print(elapsed: {:.2f}s.format(elapsed)) print(total TPS: {:.2f}.format(total_tps)) if __name__ __main__: asyncio.run(main())这个脚本的关键点是它是用 16 个并发请求测“系统总吞吐”不是测“单流 TPS”。如果要对标排行榜需要把并发调成 1并统计单条请求的生成 token 数和时间。4.4 从部署角度重新理解 2158 tokens/s假设 Celeris-1 的 2158 tokens/s 来自单流最优配置生产部署时不能直接按这个值做容量规划。原因很简单多用户并发时单流速度会下降。流式响应的网络传输和客户端解析会消耗时间。长上下文和 KV Cache 压力会降低有效并发。服务还需要留出 CPU、内存和显存余量处理突发请求和模型升级。通常的容量规划做法是先在目标并发和输入输出长度下压测出 p50/p95 TTFT 和 TPS再按业务延迟要求反向计算单机最多支撑多少用户。2158 tokens/s 只能作为一个极限参考不能作为线上服务能力的保证。5. 推理变慢时的排查链路5.1 按顺序检查输入、显存、缓存和并发服务上线后如果用户反馈“回答变慢了”不要直接怀疑模型先按下面顺序排查问题现象常见原因检查方式处理建议所有请求都变慢GPU 显存不足推理引擎频繁换入换出nvidia-smi观察显存利用率降低 gpu-memory-utilization减少最大并发首 token 特别慢prefill 过长或排队请求多查看服务日志中的 queue time 和 prefill time减少单请求最大输入长度增加 prefill 并行度生成速度忽快忽慢并发请求动态加入 batch单流 TPS 波动对比不同并发下的 TPS 曲线限制 max-num-seqs或分离在线服务和异步任务长文档处理极慢长输入导致 KV Cache 占用过高查看显存使用和 max-model-len 配置缩短单请求上下文或用 prefix caching单流很快多人用就超时吞吐和延迟之间没有平衡压测不同并发下的 TPS 和 TTFT 分位数增加实例数或调整 max-num-seqs5.2 用服务端指标定位瓶颈vLLM 的日志会输出每轮请求的 prefill、decode 耗时和当前 running 序列数。通过这些信息可以判断瓶颈在哪个阶段queue time 高请求在排队说明实例处理不过来优先扩容或调高并发上限。prefill time 高输入很长或 prefill 算子不够快优先优化输入长度、启用 chunked prefill。decode time 高单 token 输出慢优先看显存带宽、权重精度、batch 大小。num_running_seq 长期打满并发已经到上限继续加请求只会增加排队时间。这些指标比单纯看 TPS 更能定位具体慢在哪个环节。5.3 提升 TPS 的典型优化路径如果确认模型本身没问题只是硬件和资源配置导致速度不够可以按下面的顺序做优化先做权重精度优化比如把 FP16 切到 INT8 或 INT4观察 TPS 提升和输出质量变化。再确认推理引擎版本和参数升级到较新版本检查是否开启 Continuous Batching。接着调整max-num-seqs和并发模型找到吞吐与延迟的平衡点。如果生成很长且单流速度是主要诉求尝试投机解码配置草稿模型。最后考虑张量并行或多实例横向扩展解决单卡能力不足的问题。每做一步都要用固定口径重新压测一次记录 TTFT、TPS 和显存使用再决定是否继续下一步。6. 常见坑、最佳实践与可复用清单6.1 三个容易踩的坑第一个坑是把单流 TPS 当系统吞吐。很多人看到排行榜上的 2000 多 TPS就以为线上也能支撑每秒 2000 token 的输出能力。实际上一旦并发用户数上来单流 TPS 会下降系统总吞吐才是服务能力的真实指标。写文档和做规划时必须分别标注“单流 TPS”和“系统吞吐”。第二个坑是用聊天客户端估算模型速度。聊天界面里看到的时间包含了网络延迟、前端渲染、首 token 等待和本地解析无法从体验里反推出模型的 TPS。要测速应该直接向服务端接口发请求并用日志或脚本统计时间戳和 token 数。第三个坑是不固定输入长度和输出长度就对比速度。模型生成短句子和生成长段落时TPS 统计结果完全不同。对比不同版本、不同引擎时必须固定输入 token 数、输出 token 数和并发数否则结论不可重复。第四个坑也比较常见只看到量化后 TPS 上涨没有验证输出质量。INT4 量化确实能显著提速但某些业务场景里会损失准确性、格式稳定性或代码可编译性。上线前要在有代表性的评测用例上对比量化前后结果。6.2 部署前测速与调优清单下面的清单可以复制到本地在每次发布或升级模型时逐项确认检查项确认内容通过标准环境固定GPU、驱动、CUDA、推理引擎版本已记录文档可复现权重精度FP16/INT8/INT4 已明确且质量评测已通过有对比结果测速口径输入长度、输出长度、并发数已固定数据可对比单流性能记录单流 TPS 和 TPOT达到业务预期并发性能记录目标并发下的总吞吐和 TTFT 分位数p95 延迟在 SLA 内显存余量nvidia-smi显示显存使用率不过高预留约 10%-20%异常验证长输入、超长输出、并发突增时不崩溃有保护措施和错误提示资金与成本记录单卡吞吐和单位 token 成本成本可接受6.3 下一步扩展方向如果已经能稳定复现和提升 TPS下面几个方向值得继续深入结构化输出加速在 JSON 输出、代码生成等场景中通过约束解码减少无效 token 生成。Prompt Cache对固定系统提示词和长文档前缀做缓存降低 prefill 耗时。PD 分离部署把 prefill 和 decode 放到不同显卡上执行解决长输入高并发场景的互相干扰。多模态 token 优化图片和视频输入会显著改变 token 构成测速口径需要重新设计。更细粒度的监控把 TTFT、TPOT、排队时间、缓存命中率接入监控系统形成长期趋势。回到开头的问题。Celeris-1 的 2158 tokens/s 是一个有价值的参考点但它不是一把可以直接搬到所有场景的尺子。真正可靠的方式是把测评条件写清楚、把并发口径固定住再回到自己的硬件和业务里重新测一遍。速度只是模型服务体系里的一个维度质量、成本和稳定性同样需要放进同一个评估表里。对于开发者来说最好带着自己的测速清单去看任何公开的 TPS 数据而不是直接相信排名数字本身。