LLM推理性能测评:从核心指标到压测脚本的工程实践指南 最近很多人问我同样是跑一个大模型为什么别人汇报的“推理性能”那么亮眼自己一上线就卡成 PPT延迟数字看着都挺低放到生产环境里怎么完全对不上这不是模型不行也不是 GPU 不够而是大多数人对LLM Inference Benchmarking的理解还停留在“找个脚本跑一下看个 token 数”的阶段。做语言模型评测Evaluation和做推理性能评测Benchmarking是两回事。前者关心“回答得对不对”后者关心“回答得多快、多稳、多省”。两者都需要测但方法论完全不同。本文要讲的是后者如何科学地评测一个 LLM 推理系统的性能。这篇文章会带你走通从“概念 → 指标 → 测试脚本 → 结果分析 → 生产环境风险”的完整链路。如果你正在做模型部署、网关开发、推理框架选型或者要给业务方一个可信的容量评估报告这篇文章值得收藏。1. 为什么 LLM 推理 Benchmarking 这么容易被误读先回答一个核心问题为什么同样是 70B 模型有的团队说吞吐能到几千 token/s有的团队说首字延迟要两秒两个数字都对只是测的不是同一个东西。很多团队在宣传某个推理框架时喜欢报一个“极端吞吐数字”。这个数字通常是在长 prompt、允许高延迟、大 batch 的条件下压出来的并不代表真实用户体验。反过来在移动端或网页聊天场景真正的决定因素是“用户从按下回车到看到第一个字的时间”。这个指标叫TTFTTime To First Token它和吞吐的关系是矛盾的为了压低首字延迟你可能不敢把请求攒太多再一起做 batch而为了把吞吐做高你可能要牺牲单用户的首字体验。这就引出推理 Benchmarking 的第一个原则不要问“这个推理服务有多快”要问“在某个人群、某个请求分布、某个成本约束下它能不能达标”。实际中最常见的误解是直接用单并发测试结果估计生产容量。不区分 prefilling预填充和 decoding解码阶段的耗时。只测平均延迟不测尾延迟。没有预热模型拿缓存冷启动的数据充数。压测时间太短没有观察显存碎片和内存增长。这些坑后面都会一一展开。2. LLM 推理的基本流程与 Benchmarking 的关系要测准先得搞清楚一个请求在推理系统里到底经历了什么。2.1 推理全过程拆解一次 LLM 请求可以被分成两个阶段Prefilling预填充阶段。用户输入的 prompt 被编码成 token模型需要把这些 token 并行地“读进去”层层计算并生成 Key/Value 缓存KV Cache。这个阶段是计算密集型的GPU 利用率往往可以拉得很高。它的耗时大致和 prompt 长度成正比。Decoding解码阶段。模型每生成一个 token就把这个 token 放进序列再次读取 KV Cache预测下一个 token。这个阶段是访存密集型的瓶颈往往不是算力而是显存带宽。有意思的是实测一个 7B 模型时Decoding 阶段单个 token 的耗时可能远大于你按 Prefilling 阶段的总 token 数除以同时长算出来的均值。如果你用“总 token 数 / 总时间”去推单 token 时延会有偏差。2.2 动态 Batching 让情况变得更复杂现代推理服务不会一次只处理一个请求。多个请求会被Continuous Batching连续批处理或类似机制拼在一起。当一个请求处于 Decoding 阶段、正在慢慢吐词时另一个新请求的 Prefilling 阶段可以插进来共享一颗 GPU。这种方式大幅提高了吞吐但也让“某个请求的延迟”不再是独立变量而是取决于此刻 GPU 上还有多少并发请求。因此在 Benchmarking 时必须明确并发模型、请求到达模式、输入输出长度分布。否则任何延迟数字都只是在特定环境下的一次快照。3. LLM 推理性能评测的核心指标评测一个 LLM 推理服务不能只测一个指标。这里列出一组最常用的指标以及它们各自在什么场景下最重要。3.1 TTFTTime To First Token定义从请求发起到服务端返回第一个 token 的耗时。聊天场景的“字出来得快不快”主要看它。用户通常希望 TTFT 在 1 秒以内这也是学术界和工业界最常见的 SLA 分位线。3.2 TPOTTime Per Output Token定义解码阶段每输出一个 token 的平均耗时。计算方式可以是用生成阶段的墙钟时间除以生成的 token 数量。用户感知的“打字速度”就是由 TPOT 决定的。3.3 ITLInter-Token Latency定义两个相邻输出 token 之间的时间间隔。TPOT 是一个平均值ITL 能看出输出是否均匀。如果某段时间 GPU 在忙别的大请求ITL 可能突然飙升表现为模型的字“卡一下才继续出来”。3.4 Throughput吞吐定义服务在单位时间内能处理的请求数或生成的 token 数。常用的有requests/soutput tokens/sBatch 推理和在线交互场景对吞吐的定义不完全一致建议报告时注明是“总输出 token / 总墙钟时间”。3.5 并发与 QPSQuery Per Second在固定并发数下测试可以得到不同 QPS 时的延迟曲线。注意QPS 提升到一定程度后队列会排队延迟会非线性上涨。评测时最好能找到那个“服务还能稳定运行”的拐点。3.6 分位延迟只看 p50 是不够的尾延迟更重要。在生产环境核心指标建议看 p95、p99聊天场景甚至要看 p99.9。p99 延迟很高但 p50 很低的系统说明存在明显的长尾波动可能是热点请求或批调度不均。指标关心问题典型影响场景TTFT用户多久看到第一个字在线对话、语音交互TPOT生成的整体速度是否流畅写作助手、翻译、总结ITL输出过程是否卡顿流式输出、代码补全Throughput单位时间能服务多少请求离线批处理、容量规划p99 尾延迟最差体验是否能接受企业级 SLA、网关超时显存占用能否稳定运行不 OOM长上下文、高并发服务4. LLM 推理 Benchmarking 的常见方法框架很多人第一次做推理压测第一反应是“用 curl 发一个请求看时间”。这不是不对而是不够系统。下面梳理一套可复用的评测流程这套流程不会绑死某个供应商而是适配绝大多数 OpenAI 兼容协议的推理服务。4.1 评测步骤总览确定评测目标你是想看容量上限还是想验证一个用户路径的体验。校准输入负载使用与真实场景匹配的 prompt 长度、输出长度和并发数。准备标准数据集或合成请求。预热服务。运行多轮测试延长观测时间。记录原始日志并计算指标。分析长尾和异常输出结论。4.2 需要注意的干扰因素GPU 频率波动和散热相邻测试之间要留冷却时间否则结果会受到影响。显存缓存服务端如果开了 prefix caching会显著降低重复 prompt 的耗时。这可能导致结果不可比。如果目标是评测“系统能力”建议在测试中混入足够多的 prompt 前缀如果是评测“真实场景”可以把缓存命中率作为变量记录。日志输出打印每步的 debug 日志会消耗 CPU 并掩盖真实请求开销。网络延迟如果并发压测的客户端和服务端在同一台机器网络开销会被低估。建议将压测客户端部署在与服务端低延迟但稳定的网络环境中。5. 环境准备与最小实验设计这里给出一套可以照着操作的最小方案。假设你手上有一张支持量化运行的 GPU如果没有可以用满足最低显存需求的云主机 CPU 推理来体验流程指标趋势仍然有参考价值。5.1 组件说明组件作用推理服务端加载模型并暴露 HTTP API压测客户端模拟并发请求收集响应数据集定义请求的 prompt 与期望输出长度如果你要快速跑通整个 Benchmarking 流程我推荐用以下技术栈之一vLLM 或 SGLang 作为 OpenAI 兼容的推理服务自写 Python 多线程脚本作为压测客户端用一个包含 200~2000 条 prompt 的测试集作为负载5.2 模型与硬件说明本文不限定具体模型名称运行命令中出现的模型路径需要替换为你的本地模型路径或你有权通过 API 访问的模型标识。如果你的 GPU 显存在 24GB 以下建议优先尝试 7B~14B 的量化模型来跑通流程如果显存充足则用 70B 以上模型观察 Prefill/Decode 的差异。推理框架的版本请以官方最新稳定版为准。5.3 启动一个最小推理服务这里以 vLLM 为例。vLLM 暴露的 API 兼容 OpenAI 格式便于后面用统一脚本压测。先安装依赖pip install vllm启动服务需要按实际模型路径替换python -m vllm.entrypoints.openai.api_server \ --model /path/to/your-model \ --served-model-name test-model \ --gpu-memory-utilization 0.90 \ --max-model-len 8192 \ --port 8000启动成功后服务会打印监听的地址。我们可以先用一个请求验证服务正常curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: test-model, messages: [{role: user, content: 你好介绍一下你自己}], max_tokens: 128, stream: false }返回结果里有usage.completion_tokens说明服务端可以正常生成内容。6. 用 Python 实现一个可复用的推理性能测试脚本这里给出一个用标准库 requests 实现的压测客户端。它足够简洁不会引入太重的学习成本同时又覆盖了 TTFT、TPOT、吞吐和分位延迟的计算。6.1 脚本功能说明脚本会做几件事从文件中读取若干 prompt。使用线程池模拟并发请求。每个请求记录请求开始时间、首 token 时间、首个 token 结束时间、完整完成时间。计算 TTFT、TPOT、总耗时。汇总输出 p50 / p95 / p99 和吞吐。6.2 完整代码示例# 文件路径bench_llm.py import json import time import threading import statistics from concurrent.futures import ThreadPoolExecutor from dataclasses import dataclass, field from typing import List, Optional import requests API_URL http://127.0.0.1:8000/v1/chat/completions MODEL_NAME test-model MAX_TOKENS 256 CONCURRENCY 8 REQUESTS_PER_WORKER 10 PROMPT_FILE prompts.jsonl dataclass class RequestResult: ttft: Optional[float] None # 首 token 延迟 completion_time: Optional[float] None # 总完成时间 output_tokens: int 0 total_tokens: int 0 error: Optional[str] None def load_prompts(path: str, limit: int 500) - List[str]: prompts [] with open(path, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue obj json.loads(line) prompts.append(obj.get(prompt, )) if len(prompts) limit: break if not prompts: prompts [请用中文写一段关于人工智能发展的简介。] return prompts def send_one_request(prompt: str) - RequestResult: result RequestResult() payload { model: MODEL_NAME, messages: [{role: user, content: prompt}], max_tokens: MAX_TOKENS, stream: True, } start time.perf_counter() try: with requests.post(API_URL, jsonpayload, streamTrue, timeout120) as resp: resp.raise_for_status() first_token_time None accumulated for raw_line in resp.iter_lines(decode_unicodeTrue): if not raw_line: continue if raw_line.startswith(data:): data_str raw_line[len(data:):].strip() else: data_str raw_line if data_str [DONE]: break try: chunk json.loads(data_str) except json.JSONDecodeError: continue choices chunk.get(choices) or [] if not choices: continue delta choices[0].get(delta) or {} text_piece delta.get(content) or usage chunk.get(usage) if text_piece and first_token_time is None: first_token_time time.perf_counter() if usage: result.output_tokens usage.get(completion_tokens, 0) result.total_tokens usage.get(total_tokens, 0) end time.perf_counter() if first_token_time is not None: result.ttft first_token_time - start result.completion_time end - start except Exception as exc: result.error str(exc) return result def run_benchmark() - List[RequestResult]: prompts load_prompts(PROMPT_FILE) tasks [] for worker in range(CONCURRENCY): for _ in range(REQUESTS_PER_WORKER): tasks.append(prompts[(worker len(prompts)) % len(prompts)]) results: List[RequestResult] [] lock threading.Lock() def worker_task(prompt: str): r send_one_request(prompt) with lock: results.append(r) with ThreadPoolExecutor(max_workersCONCURRENCY) as executor: futures [executor.submit(worker_task, p) for p in tasks] for f in futures: f.result() # 等待所有线程结束 return results def _percentile(values: List[float], percent: float) - Optional[float]: if not values: return None sorted_values sorted(values) idx max(0, int(len(sorted_values) * percent / 100) - 1) return sorted_values[idx] def print_report(results: List[RequestResult]): ttft_values [r.ttft for r in results if r.ttft is not None] total_time_values [r.completion_time for r in results if r.completion_time is not None] total_output_tokens sum(r.output_tokens for r in results) wall_time_start time.perf_counter() time.sleep(0.001) # 这里不用做太多时间统计主要展示汇总结果 print( LLM Inference Benchmark Report ) print(fTotal requests: {len(results)}) print(fError requests: {len([r for r in results if r.error])}) print(fTotal output tokens: {total_output_tokens}) print() if ttft_values: print(fTTFT p50 : {_percentile(ttft_values, 50):.3f} s) print(fTTFT p95 : {_percentile(ttft_values, 95):.3f} s) print(fTTFT p99 : {_percentile(ttft_values, 99):.3f} s) if total_time_values: print(fTotal time p50: {_percentile(total_time_values, 50):.3f} s) print(fTotal time p95: {_percentile(total_time_values, 95):.3f} s) print() if __name__ __main__: results run_benchmark() print_report(results)需要说明脚本中的 usage 信息并不是所有推理服务都会在流式响应里带最后一条 usage 数据。如果服务端不返回 usage你可以改用字符级统计或按 tokenizer 估算。这段代码更重要的价值在于给你展示了如何记录首 token 时间和完整时间。6.3 准备测试数据可以在prompts.jsonl中准备一批中文文本每行是一条 JSON{prompt: 请写一篇关于量子计算的科普短文不少于200字。} {prompt: 解释一下什么是反向传播算法并给出一个教学案例。} {prompt: 帮我列出云计算和边缘计算的区别使用表格回答。}在生成测试数据时记得控制前几个测试固定为短 prompt、短输出以便快速验证链路后续再加长 prompt。6.4 运行压测python bench_llm.py运行结束后脚本会输出 TTFT 的 p50 / p95 / p99以及总完成时间。如果 p95 远远高于 p50说明并发调度有不稳定因素值得继续排查。7. 如何分析测试结果不是所有延迟高都怪模型拿到结果后第一反应不要太快。以下是我建议的分析顺序。7.1 先看错误率如果错误率超过 0说明系统在目标并发下已经不稳定了后面的指标参考价值有限。优先排查超时、连接拒绝、显存不足等错误。7.2 看 TTFT 是否符合用户体验预期如果 TTFT 的 p95 超过 2 秒聊天类业务的体感就会非常差。此时要关注请求是否在排队。服务端最大并发数是否设置得太低。Prefill 阶段是否过于耗时。7.3 看 TPOT / ITL 是否均匀如果总完成时间正常但 ITL 有显著波动说明解码阶段被长请求的 Prefill 挤占了。部分推理服务允许开启chunked prefill把长 prompt 的预填充拆碎穿插到解码流程中即“分块预填充”。那样可以降低 ITL 波动但会轻微增加响应整体的处理耗时。7.4 对比不同并发下的吞吐曲线建议将并发数从 1、2、4、8、16、32 依次加压。记录每个并发下的 Throughput 和延迟。你会发现并发太低时显存可能没满吞吐没有拉满。并发逐步提高延迟缓慢增长吞吐持续上升。并发超过某个阈值延迟快速上涨吞吐增长变缓甚至下降。这个“拐点”对容量规划非常关键。如果生产环境要求 p99 延迟低于某个阈值就不应该把并发压到理论最高吞吐点。8. LLM 推理 Benchmarking 常见误区与排查方法误区可能后果排查与解决只在单并发下测延迟严重低估生产环境的排队开销至少按 1/8/16/32 多组并发测试请求长度不一致平均延迟被长请求带偏难以横向对比按输入输出长度分段统计不预热直接压测第一次请求需要加载 CUDA kernel 和权重结果异常高先发 10~50 个请求预热观察稳定后重新测试测试时间太短长时间运行后可能出现显存碎片、OOM、变慢至少持续 5~10 分钟观察趋势忽略客户端网络开销延迟被高估主要是网络等待将客户端部署在靠近服务端的可靠网络或做本地回环测试混淆 Prefill 和 Decode 优化只看总耗时难以定位瓶颈分开记录 prefill 与 decode 耗时使用完全重复 promptprefix cache 让结果失真准备多样化的 prompt并注明是否命中缓存依赖默认的全局温度与采样参数不同采样路径耗时不同固定 seed 和 sampling 参数保证可复现真实项目里最容易被忽略的是“预热不足”。有团队曾把预热不足时的 TTFT 当成服务真实水平结果在压测报告里写了一个比正常值高几倍的数字导致容量评估出现偏差。9. LLM 推理评测结果与生产容量规划的对接Benchmarking 的最终目的是服务上线前的容量规划。这里给一个简单的换算思路。假设你有以下测量值单请求平均输出长度300 token单并发下 TPOT20 ms/token即 50 token/s目标吞吐500 并发用户中可能有 50 个同时在线请求你可以估算单个请求平均耗时约为 300 * 20ms 6 秒。如果一个用户平均每 30 秒发一次请求单用户稳态负载约为总时间占比的 20%。50 个活跃用户同时对系统产生请求的概率需要用排队论估算但通常取一个合理的并发因子。在容量规划中最忌讳的是“用户数乘以最差情况延迟”的粗暴估算。正确做法是建立一个小规模真实负载压测平台利用采集到的 p95 延迟和吞吐曲线反推网关限流阈值。如果团队还没有建设压力测试平台建议第一步先做两件事用结构化日志记录每次请求的 prompt 长度、输出长度、TTFT、TPOT。在网关层暴露这些指标到监控便于后续做容量预测。10. 面向真实场景的 LLM 推理评测实践建议10.1 不同场景应该使用不同侧重点场景不同Benchmarking 的指标权重完全不同智能客服TTFT 要低同时要有足够大的并发吞吐支持。离线数据处理吞吐优先延迟不敏感允许较大 batch。代码补全ITL 很重要因为用户正在打字模型给出的补全需要跟上节奏。Agent 工具调用总延迟和函数调用准确性更关键因为可能涉及多轮工具调用。必要时应该在评测报告里把指标按场景拆开而不是只给一张总表。10.2 固定采样与随机种子采样策略会显著影响生成 token 数量。同一个 prompt如果 temperature 很高模型可能输出更长或更短的内容导致总耗时不可比。评测时建议固定temperature0、固定seed并且固定max_tokens。10.3 prompt 长度分布要尽量贴近真实不要只测“短 prompt 长输出”或“长 prompt 短输出”。真实业务里的用户输入长度通常呈偏态分布客服场景 prompt 包含用户问题 历史上下文可能很长。闲聊场景 prompt 很短但输出长度随机。RAG 场景中文档检索结果和指令模板拼接后prompt 可能达到 2000~6000 token。你可以从线上日志里抽样统计 prompt 长度分布然后按比例构造压测请求。10.4 保护生产集群与数据压测时如果目标服务连接的是包含用户数据的生产环境一定要确认请求不会写入实际业务库也不会触发发送短信、邮件等外部动作。评测 LLM 推理性能还需要注意使用最小权限账号启动服务。在测试环境或隔离的 GPU 资源组中执行。如果必须对生产服务压测先和平台与运维团队确认容量水位建议从低并发开始逐步加压。11. LLM 推理性能评测的主流工具与配套组件如果你不想重复造轮子可以了解下面几类工具11.1 推理服务框架自带压测能力vLLM 社区有一些 benchmark 脚本通常在仓库的benchmarks目录下用于测试吞吐和延迟。SGLang 同样提供官方 benchmark 脚本。TensorRT-LLM 部署后可用inflight_batcher_benchmark执行基准测试。这类工具与框架本身深度绑定适合评估框架内部不同参数的效果。11.2 通用 API 压测工具如果你已经通过网关对外提供服务API 层压测更适合使用通用工具。这类工具能更真实地还原网络链路。k6支持 TypeScript 编写压测脚本可以较方便地模拟流式响应。LocustPython 生态写请求逻辑更自由容易和自定义指标采集集成。wrk / ghz偏 HTTP/gRPC 层压测适合攻坚持久层能力。11.3 可观测性工具指标的可靠性最终取决于可观测性系统。建议接入 Prometheus Grafana对推理服务的关键指标做实时监控。要注意区分“业务指标”和“系统指标”。系统指标如 GPU 利用率、显存使用、显存带宽、GPU 温度适合通过 NVIDIA 官方的dcgm或nvidia-smi采集。业务指标如 TTFT、TPOT、吞吐、p99适合在推理服务端或网关层通过日志埋点导出。11.4 引入 Profiling 定位阶段瓶颈如果发现性能不符合预期只靠黑盒压测仍然不够。你还需要结合 profiler 观察 GPU kernel 的耗时占比判断瓶颈究竟是显存带宽不足解码阶段常见。计算核心未打满prefill 阶段受 padding 和注意力机制影响。CPU 预处理慢prompt 过长时 tokenizer 和 batch 组包开销可能被忽视。调度线程不足并发请求多时,处理不足会导致排队。NVIDIA 提供 CUDA 事件计时和 profiling 工具可以用来对照。12. 一次完整评测的示例输出与解读下面是一份虚构但结构完整的示例报告片段方便你理解如何给团队讲清楚结果。并发数QPSTTFT p95TPOT 均值输出吞吐 tokens/sp99 总延迟10.30.45s45ms226.8s41.20.62s52ms987.4s82.10.91s63ms1748.5s163.01.85s88ms21012.3s323.14.20s142ms22519.0s从这张表里可以读出几个信息并发从 1 涨到 8吞吐涨得很明显TTFT 仍在 1 秒以内这个区间属于“健康区”。并发到 16 时吞吐在持续提升但 TTFT 已经逼近两秒说明开始有明显的排队等待。并发到 32 时QPS 几乎不涨但延迟继续恶化这是典型的“过载拐点”。对于在线聊天业务这张表直接告诉你并发最好不要超过 8~12对于离线批处理任务你可以继续用 32 并发压榨吞吐只要不超时即可。换句话说同一套系统服务于不同类型业务时应该采取不同的并发与限流策略。这也是为什么“单点最优”指标没有意义必须结合业务诉求来解读。13. 跨框架对比时需要注意的细节团队做技术选型时经常要对 vLLM、SGLang、TensorRT-LLM、llama.cpp 等框架做横向 Benchmarking。跨框架对比比单独评测一个系统更复杂因为要保证公平性。需要注意这些点使用同一模型权重文件和同一精度FP16 / BF16 / INT8 / INT4。固定相同的max_model_len和gpu_memory_utilization。显存分配策略不同可能会影响后续 batching 的上限。设置相同的采样参数和max_tokens。尽量使用同一版本的 CUDA、PyTorch 和 GPU 驱动。推理框架对底层运行时的依赖差异显著。预热时间和总测试时长需要一致。需要确认是否开启 prefix caching或明确标注缓存命中情况。跨框架对比不可能做到绝对公平但至少要让所有被测对象运行在同一个目标环境下并把可调参数调整到各自较为合理的生产配置。否则“谁跑得快”只能反映“谁的默认参数更好”。14. 生产环境长期评测与常态监控建议性能评测不是上线前做一次就结束了。模型在迭代、框架在升级、GPU 驱动在变化线上流量分布也在变化。推理性能的可观测性应当成为平台工程的一部分。建议把以下几项纳入常态化监控14.1 业务延迟分层监控在网关层记录“客户端到网关”“网关到推理服务”“推理服务响应首字”“完成全部输出”几个阶段的时间这样可以快速定位延迟来自网络链路、排队还是模型生成。14.2 限流与排队指标在推理服务入口记录排队请求数。如果队尾持续增长说明上游 QPS 已经超过服务容量仅看平均延迟可能被整体抬高。14.3 长尾分布跟踪延迟监控不仅要有平均值还要保留 p95、p99 甚至 p99.9。任何短时间抖动都会在长尾上反映出来。14.4 请求内容分布监控由于 LLM 推理耗时和输入输出长度强相关建议对 prompt token 数与 completion token 数做分桶统计比如 0~128、128~1024、1024~4096。当某个桶的延迟突然变高时能够更准确地定位问题。14.5 版本变更验收流程每次升级推理框架版本或修改服务参数都应该重新跑一次既有的基准测试集形成对比报告。没有经过基准测试的版本尽量不直接发布到生产。15. LLM 推理优化的下一步方向如果你已经能完成标准 Benchmarking下一步可以从这些方向继续深入。15.1 Speculative Decoding推测解码通过小模型先草拟多个 token再交给大模型一次性验证可以降低解码阶段的耗时。但这种优化对 benchmark 的影响比较微妙单请求延迟可能下降但吞吐不一定线性上升。压测时也需要评估 CPU 侧额外开销。15.2 Prefix Caching前缀缓存如果业务中存在大量共享系统提示词或历史文档片段缓存这些前缀的 KV 可以大幅降低 TTFT。基准测试时如果开启该功能必须设计带共享前缀的请求集否则测不出预期收益。15.3 量化与 KV Cache 压缩使用 FP8 / INT8 / INT4 量化可以把模型压缩到更小部分场景能让显存容纳更多并发。但量化后的精度损失需要结合任务效果判断。压缩 KV Cache 同理都需要引入“模型质量和推理性能”的综合评估否则容易片面追求速度。15.4 多机多卡分布式推理当单卡放不下模型时需要考虑张量并行或流水线并行并行度提升会带来通信开销。Benchmarking 时必须记录卡数和并行策略否则无法归因到底层是通信瓶颈还是计算瓶颈。15.5 与 RAG/Agent 链路结合真实业务往往不是简单的一来一回而是多次工具调用和多轮检索。评测范围如果只到单次 LLM 请求可能低估系统整体延迟。更完整的评测应该包含请求是否经过检索。提示词构建是否耗时。工具调用是否触发了外部服务的额外等待。多轮对话历史是否需要重算。16. 给不同角色的最终建议如果你是算法工程师重点研究模型与推理框架的组合收益但不要只报一个好看的数字。建议把评测脚本和测试数据版本化管理方便后续对比。如果你是后端工程师重点把延迟和吞吐接口标准化把指标接入告警让性能问题在上线前就暴露。如果你是技术管理者不要追求“最大化吞吐”这一个目标。先明确业务对延迟的底线再反推并发上限和基础设施成本。评测结论最好包含“在什么条件下系统能服务多少用户成本是多少”这样才具备决策价值。17. 小结与直接可执行的下一步LLM Inference Benchmarking 不是跑一个脚本、拿几个指标就结束的“一次性动作”而是从测试设计、指标定义、并发模型、生产对接、长期监控串起来的一套工程能力。这篇文章覆盖的核心链路是理解 LLM 推理的 Prefill/Decode 两阶段以及动态批处理对指标的影响。掌握 TTFT、TPOT、ITL、吞吐、分位延迟等指标的含义。知道如何用 OpenAI 兼容协议的服务配合自写脚本做最小压测。能够判断测试结果是否可靠避开缓存、预热、请求分布等坑。能够把单次压测结果转化成容量规划和业务监控的依据。如果你现在正准备开始一次推理性能评测建议按下面的顺序行动选定一个推理框架并在隔离环境启动模型服务。先跑 20 个单并发请求确认链路通、指标能取到。再按 1/4/8/16/32 五档并发跑完整流程。记录每组结果的 TTFT、TPOT、p99 和吞吐。把产出整理成一份“不同并发下延迟和吞吐对照表”用于后续与业务方对齐容量预期。推理性能评测的真正难点不在遥不可及的底层代码而在于你是否能把“模型生成策略、推理服务、请求负载、并发模型”这几个变量控制住然后诚实回答一个问题这套系统在业务真正需要的并发下体验还是不是达标的。只要你的评测流程是可控、可复现、可解释的你就已经比大多数只会在群里晒吞吐数字的团队靠谱了。