Skip to content

性能调优是大模型应用从"能跑通"走向"能用、好用、用得起"的最后一公里。一个 RAG 应用在内部 Demo 里回答延迟 800ms,到了客户生产环境却飙升到 10 秒——这种 12 倍劣化在生产中是常态而非例外,根因往往不是模型本身,而是全链路中某一层没有被正确测量和优化。本专题以 FDE 视角,从分层定位、关键指标、各层调优手段、Profiling 工具链、成本控制到决策树与真实案例,给出一套可复刻的工程方法论。

一、性能问题的分层定位:先定位,再优化

大模型应用是一个端到端链路,任何环节的瓶颈都会被放大为用户感知的"慢"。盲目调优最大的陷阱是在错误层用力——比如把 GPU 量化做到 4-bit 仍无法改善延迟,结果发现真正瓶颈是网关层串行的鉴权调用。正确的姿势是先分层、逐层量化、定位真实瓶颈。

一条典型的请求链路分为六层:

  1. 网络层:用户到入口的 RTT、TLS 握手、跨境光缆抖动。境内调用境外 API 时这一层常是主因。
  2. 网关层:鉴权、限流、配额、日志、协议转换(HTTP↔gRPC、SSE 转发)。一个同步写审计日志到数据库的网关可以让 P99 涨 300ms。
  3. 推理层:模型前向计算、KV cache 分配、batching 调度、queueing 排队。
  4. 检索层:向量检索、重排、与外部知识库的网络往返。
  5. Agent/编排层:工具调用、多步推理、子任务串并行调度。
  6. 业务层:DB 读写、第三方 API、模板渲染、上下文拼接。

定位铁律:永远先测量,再优化。没有 trace 的调优等于盲飞。

定位的第一步是建立"全链路 trace 视图"。在网关入口注入一个 trace_id,逐层透传,每层记录 enter/exit 时间戳。生产环境必备的最小观测三件套:结构化日志(带 trace_id 与各段耗时)、metrics(分位延迟 P50/P95/P99)、分布式 trace(跨服务调用关系)。LangSmith、Langfuse、OpenTelemetry 都能产出"火焰图式"的 span 视图,一眼看出哪一段是热点。

实践中一个高频误判:用户报"AI 很慢",产品团队直觉归因于"模型大"。FDE 现场测一次会发现,P99 10 秒里模型只占 1.2 秒,其余 8.8 秒消耗在:网关鉴权调用一个慢的权限服务(2 秒)、检索重排模型串行三次(3.5 秒)、Agent 等外部工具 API 超时(3 秒)、剩下零碎是序列化与网络。修掉后三个,延迟立刻降到 2 秒以内,模型一个参数没动。

二、关键指标:必须先定义"快"是什么

性能优化没有终点,只有相对目标的逼近。开始前必须和业务对齐四个指标的优先级,因为它们彼此冲突:

  • TTFT(Time To First Token,首 token 延迟):用户发出请求到收到第一个 token 的耗时。决定"感觉是否卡顿",对话类场景的命脉。流式输出下用户对 TTFT 极敏感,>2s 就会觉得"AI 在思考太久"。
  • TPOT(Time Per Output Token,每 token 延迟):生成阶段平均每输出一个 token 的时间。决定"打字速度"。人类阅读舒适带约 30-50 token/s,即 TPOT 20-33ms。低于这个速度,用户感觉"AI 结巴"。
  • 吞吐(Throughput):单位时间系统处理请求数(req/s)或 token 数(token/s)。决定单机能扛多少 QPS,是成本与扩缩容的核心。
  • 并发(Concurrency):系统同时服务的请求数。在 LLM 推理中受 KV cache 显存约束,常是硬上限。

经验阈值:对话类应用 TTFT P95 < 1.5s、TPOT P95 < 50ms 通常可接受;批处理类应用可放弃 TTFT,追求吞吐。

此外还有两个"非延迟但同属性能"的指标:

  • 成本(每千 token 价格 × 调用量):在云 API 场景下与延迟呈强相关(更快的小模型也更便宜),在自建推理场景下与吞吐强相关(单卡吞吐越高,单 token 成本越低)。
  • 可用性(SLA 达成率):性能优化不能以牺牲稳定性为代价。激进降低 KV cache 预留可能换来 OOM 雪崩。

定义指标时务必明确分位。只看平均值的优化是耍流氓:平均 800ms 可能掩盖 P99 8 秒的尾部。所有 SLO 必须以"P95/P99 在 X 秒内"形式写进合同。

三、推理层调优:显存与算力的精密配比

推理层是 LLM 应用的算力核心,也是优化空间最大的层。核心矛盾是:KV cache 占显存,显存决定并发,并发决定吞吐。优化围绕"在固定显存下塞更多并发、跑更快"展开。

1. 批处理(Continuous Batching / In-flight Batching)。 传统 static batching 等凑齐一批再发,延迟被最慢请求拖累。连续批处理在每个生成步动态把新请求加入、完成的请求踢出,GPU 利用率从 30% 提升到 80%+。vLLM、TGI、TensorRT-LLM 都内置。关键参数是 max_num_seqs(同时批处理的序列数),过大会 OOM,过小浪费算力。经验起点:A100 80G 跑 7B 模型设 256,30B 设 64。

2. PagedAttention。 vLLM 的核心创新,把 KV cache 按固定大小"页"管理(类比 OS 虚拟内存),消除碎片,显存利用率接近 100%,并发数比传统实现高 2-4 倍。直接选 vLLM 即可获得,无需调参,但要确认 gpu_memory_utilization(默认 0.9)与你的显卡余量匹配。

3. 前缀缓存(Prefix Caching / Automatic Prefix Caching)。 多个请求共享相同 system prompt 或长 few-shot 前缀时,这部分 KV cache 可复用,避免重复计算。在客服、固定模板问答场景下效果显著,TTFT 可降 40-70%。vLLM 用 --enable-prefix-caching 开启;Anthropic、OpenAI 的 prompt caching 在 API 层提供同样能力且计费打折(缓存命中部分价格约为 1/10)。关键约束:缓存键要稳定,system prompt 里塞了时间戳或随机 ID 会让缓存永远 miss,这是最常见的踩坑。

4. 量化(Quantization)。 把权重从 FP16 降到 INT8/INT4,显存与带宽近乎成比例下降,吞吐提升 1.5-3 倍。主流方案:GPTQ、AWQ、GGUF、BitsAndBytes。生产首选 AWQ(精度损失小、推理快)和 GPTQ(生态成熟)。代价是轻微精度损失(7B INT4 对比 FP16 在 MMLU 上掉 1-2 分),需 eval 评估能否接受。绝对不要在不评估精度的前提下直接上 INT4

5. 投机解码(Speculative Decoding)。 用一个小模型"猜"接下来的若干 token,大模型并行验证,命中则一次吐多个 token。Medusa、EAGLE、Lookahead Decoding 是代表方案。在代码生成、结构化输出(命中率高)场景 TPOT 可降 40-60%,在开放对话提升有限。代价:小模型选型与训练成本,以及验证失败时的浪费。

6. KV Cache 优化。 除了 PagedAttention 的内存管理,KV cache 还可通过:KV cache 量化(FP16→FP8/INT8,显存减半)、KV cache 重计算与 offload(低优先级请求把 KV 换到 CPU 内存)、Sliding Window Attention(只保留最近 N 层 KV,适合长文档)来扩并发。Mistral、Longformer 走 sliding window 路线。

推理层优化的顺序建议:先批处理 + PagedAttention(免费午餐)→ 前缀缓存(场景命中就大赚)→ 量化(精度评估通过再上)→ 投机解码与 KV cache 进阶(边际收益递减)。

四、检索层调优:别让 RAG 拖垮延迟

RAG 应用中检索常占总延迟 30-50%,在百万级向量库上 P95 可能超过 1 秒。优化要点:

1. 向量索引:HNSW 参数调优。 HNSW 是近似最近邻的事实标准,两个关键参数 M(每层邻居数,默认 16)和 ef_construction(建图时探索宽度,默认 200)决定精度与速度的权衡。ef_search(查询时探索宽度,默认与 ef_construction 相近)是最常调的运行时参数——降低 ef_search 可换 2-5 倍延迟提升,recall 略降。生产做法:在离线评估集上扫 ef_search ∈ {32, 64, 128, 256},选 recall@10 ≥ 95% 对应的最小值。Faiss IVF 系列则调 nprobe,同理。

2. 检索结果缓存。 同一 query 或语义近似的 query 重复出现时,缓存 top-K 结果命中即可省掉整个检索。语义缓存(Semantic Cache)用一个小 embedding 模型计算 query 向量,缓存最近邻 query 的答案,Redis/向量库都能实现。GPTCache、LangChain 的 RedisSemanticCache 是现成方案。命中率在客服场景常达 30-50%,直接砍掉一半检索+生成成本。

3. 批检索与并行检索。 单次请求若要查多个集合(如同时查 FAQ 库、产品库、工单库),用 asyncio.gather 并行而非串行。多 query 融合(RRF)时,批 embedding 调用比逐条调用快 5-10 倍——embedding 模型是天然的 batch 友好型。

4. 重排的取舍。 Cross-encoder 重排(如 bge-reranker、Cohere Rerank)精度高但慢(单次几十到几百 ms)。策略:只对 top-50 做重排,且在召回阶段先压到必要数量。长尾 query 可跳过重排直接走 BM25 兜底。

五、Agent 层调优:步数与小模型分流

Agent 是延迟放大的重灾区——一个 5 步 ReAct 循环,每步含一次 LLM 调用加一次工具调用,串行下来轻松 20 秒+。优化思路:

1. 步数控制。 限定 max_iterations,超过即强制收口或转人工。在 prompt 中明确"最多 N 步",配合早停(检测到答案或卡死循环立即终止)。OpenAI Function Calling 的 max_tokens 与 step 上限要双控。

2. 小模型分流。 把简单子任务(分类、路由、字段抽取、判断是否需要工具)交给 Haiku/3B 级模型,只把复杂推理留给 Opus/70B。一个典型路由 Agent:Haiku 判意图(50ms)→ 80% 的简单请求直接走模板答案,20% 复杂请求才进 Sonnet/Opus 主循环。整体 P50 能从 8s 压到 1.5s。

3. 并行工具调用。 多个独立工具用 Parallel Function Calling(OpenAI、Anthropic 都支持)一次发起,等待用 asyncio.wait。串行 3 次外部 API(各 500ms)变并行后只占 500ms。

4. 工具结果缓存与去重。 Agent 循环里常重复调用同一工具同一参数(尤其是搜索类),加 in-process LRU 缓存即可消除。

5. 流式 + 早期返回。 在用户感知层面,Agent 第一步就能开始流式输出"正在为您查询…",利用感知延迟掩盖真实延迟。UX 层优化常比纯技术优化收益更大。

六、网络与网关:被低估的延迟来源

1. 连接复用(Keep-Alive / HTTP2)。 每次 TLS 握手 100-300ms,短连接在低 QPS 下也是主因。网关到推理服务、到外部 API 都强制 HTTP keep-alive 或 gRPC 长连接。SDK 层用连接池(httpx.AsyncClient 全局复用而非每次 new)。

2. 流式(SSE/WebSocket)。 必须用流式把 TTFT 从"全生成完才返回"拉到"首 token 即返回"。SSE 是事实标准,但要注意中间代理(Nginx、CDN)默认会 buffer,必须显式关 proxy_buffering off; 否则流式失效变成一次性返回。

3. CDN 与边缘。 静态资源(JS、模型文件下载)、API 网关入口都可走 CDN。境内访问境外 API 必须考虑就近接入点(OpenAI、Anthropic 都有亚太入口)。模型权重分发用对象存储 + CDN 加速冷启动。

4. 网关异步化。 鉴权、配额检查、审计日志全部异步化或批量写,绝不放在请求关键路径。用 Redis 做配额、用 Kafka 异步审计。一个同步写 DB 的鉴权钩子能让 P99 涨 200ms。

七、Profiling 工具链:测量是一切的起点

没有工具的调优都是猜测。三套工具必须配齐:

1. vLLM metrics。 vLLM 暴露 Prometheus 端口(/metrics),核心指标:vllm:num_requests_running(运行中)、vllm:num_requests_waiting(排队中,>0 说明吞吐饱和,需扩容或加大 max_num_seqs)、vllm:time_to_first_token_secondsvllm:time_per_output_token_secondsvllm:gpu_cache_usage_perc(KV cache 占用率,接近 1.0 会被 eviction)。在 Grafana 建面板盯这几个指标,排阛建立即报警。

2. PyTorch Profiler。 自建推理或定位模型内部瓶颈时用 torch.profiler.profile,产出 Chrome trace 可视化。能看出 forward 各层耗时、CPU↔GPU 拷贝、kernel launch 开销。定位"为什么我的自定义模型比 vLLM 慢 3 倍"这类问题的利器。命令示例:

python
with torch.profiler.profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
    record_shapes=True,
) as prof:
    with record_function("model_inference"):
        out = model.generate(**inputs)
print(prof.key_averages().table(sort_by="cuda_time_total"))

3. LangSmith / Langfuse trace。 应用层 trace,每个 chain/agent 步骤一个 span,显示 prompt、token 数、耗时、成本。一眼看出"这次调用 LLM 占 1.2s、检索占 3.5s、工具等待占 4s"。LangSmith 是 LangChain 原生,Langfuse 开源可自部署,两者都能产出链路火焰图。

4. 系统级工具。 nvidia-smi dmon -s u(GPU 利用率与显存)、nvidia-smi pmon(per-process)、htopiostattcpdump/wireshark(网络抖动)、py-spy(Python 采样 profile)。

Profiling 原则:生产采样、测试压测。生产环境持续开 PyTorch profiler 会拖性能,只在压测或灰度环境全开。生产靠 metrics 与 sampling trace 监控,出问题再针对性 profile。

八、成本调优:用最少的钱办最大的事

成本是性能的另一个维度,尤其在使用商业 API 时。四把刀:

1. 模型分级(Model Routing)。 不所有请求都上 Opus。建一个 router(规则或小模型分类),简单请求走 Haiku,中等走 Sonnet,复杂才走 Opus。实际数据:90% 请求可用 Haiku/Sonnet 解决,整体成本降 60-80%。OpenAI 的 GPT-4o-mini、Anthropic 的 Haiku 3.5 是分流主力。

2. 缓存(语义缓存 + Prompt Caching)。 前文已述。语义缓存命中省一次完整调用;Prompt Caching 命中省前缀部分的 token 费用(Anthropic 缓存读 0.1x、缓存写 1.25x,长 system prompt 场景必开)。

3. Token 预算。 给每次调用设 max_tokens 上限,给 prompt 设长度上限,过长的 few-shot 自动裁剪。监控每用户/每会话 token 消耗,异常飙升报警。Prompt 工程里"删掉冗余 system 描述、压缩 few-shot"既是降本也是降延迟。

4. 自建 vs API 的拐点。 日均调用超某阈值后,自建推理(租 A100/H100)比调 API 便宜。粗略拐点:7B 等级模型日 50 万次以上调用、70B 等级日 5 万次以上,自建更划算。但自建带来运维成本,需把人力算进去。

九、调优决策树:症状 → 瓶颈 → 手段

面对一个"慢"的投诉,按症状走决策树:

  • 症状:TTFT 高(用户等很久才看到第一个字)

    • 检查流式是否开启 → 没开就开 SSE。
    • 检查网关是否 buffer → 关 proxy_buffering
    • 检查推理队列(num_requests_waiting 高)→ 扩容或加 max_num_seqs
    • 检查 prompt 是否过长 → 前缀缓存、prompt 压缩。
    • 检查 KV cache 是否命中 → 去掉 prompt 里的动态字段。
  • 症状:TPOT 高(打字慢)

    • 检查是否量化 → 评估上 AWQ INT4。
    • 检查 batching 利用率 → GPU 利用率低说明 batch 不够,提高 max_num_seqs
    • 检查是否可用投机解码 → 命中率高的场景上 Medusa/EAGLE。
    • 检查是否大模型 overkill → 简单任务换小模型。
  • 症状:P99 远高于 P50(长尾)

    • 看 trace 找尾部请求特征 → 通常是长 prompt、长生成、或外部工具超时。
    • 加超时与熔断 → 工具调用 timeout=3s,超时走降级。
    • 检查 GC/compaction → Python GC 偶发停顿也会拉长尾。
  • 症状:吞吐上不去(QPS 到一定值就排队)

    • GPU 利用率饱和 → 扩卡。
    • GPU 利用率低但排队 → KV cache 不够,降 gpu_memory_utilization 或量化 KV cache。
    • 网关 CPU 饱和 → 网关扩容,推理层与网关分别扩。
  • 症状:成本飙升

    • 看 token 分布 → 是否大量调用堆在 Opus。
    • 查缓存命中率 → 语义缓存、prompt caching 是否真生效。
    • 查异常用户 → 是否有滥用或循环调用。

十、真实案例:延迟从 10 秒降到 1 秒

某金融客户内部知识助手,生产环境 P95 10.2 秒,用户抱怨"比百度慢"。FDE 现场抓 100 条 trace 平均分布:

  • 网关:鉴权调用了同步查询 Oracle 用户表,平均 1.8s,P95 2.5s。
  • 检索:对三个知识库串行检索 + bge-reranker 重排 top-100,平均 3.6s。
  • Agent:ReAct 循环平均 2.3 步,每步含一次工具调用,串行等待,平均 3.2s。
  • 推理:Sonnet API,TTFT 平均 0.9s,生成 1.2s,合计 2.1s。
  • 其他(网络、序列化):约 0.5s。

总 P95 10.2s 中,模型仅占 21%,真正的成本在前三层。

优化动作(按 ROI 排序):

  1. 网关鉴权异步化:用户配额改 Redis,审计日志改 Kafka 异步,鉴权从 1.8s 降到 30ms。一周内完成,P95 从 10.2s 降到 8.4s。
  2. 检索并行化 + 重排降量:三库 asyncio.gather 并行,重排只对 top-30;语义缓存上线,命中率 38%。检索 P95 从 3.6s 降到 0.9s。P95 落到 5.5s。
  3. Agent 小模型分流 + 早停:用 Haiku 做意图判断,80% 简单查询直接走 RAG 答案不经 Agent 循环;复杂查询限定 max_iterations=3。Agent P95 从 3.2s 降到 0.6s。P95 落到 2.8s。
  4. 推理层:prompt caching 上线(system prompt 6KB 固定),命中部分 TTFT 降 0.4s;流式确保开启。推理 P95 从 2.1s 降到 1.4s。P95 落到 1.9s。
  5. 网络:网关与推理同机房部署,关 Nginx buffering,启用 HTTP2 连接复用。其他段 P95 从 0.5s 降到 0.2s。最终 P95 1.6s。

结果:P95 从 10.2s → 1.6s(降 84%),P50 从 6.5s → 0.9s。模型一个参数没动,改的全是工程。同时成本因小模型分流与缓存,单次调用均价降 45%。客户满意度从 3.2 升到 4.5。

案例启示:性能问题 70% 在工程、30% 在模型。FDE 在客户现场,优先把链路每一层测清楚,再决定动哪里。盲目换模型、加 GPU 既贵又不解决问题。

本专题小结

大模型应用性能调优不是一门玄学,而是一套"测量—定位—优化—验证"的工程闭环。核心要点:

  1. 分层定位优先:六个层(网络→网关→推理→检索→Agent→业务)逐层量化,trace 透传 trace_id,定位真实瓶颈再动手。
  2. 指标必须分位:TTFT、TPOT、吞吐、并发、成本五个指标按业务优先级排序,所有 SLO 用 P95/P99 表达。
  3. 推理层先吃免费午餐:Continuous Batching + PagedAttention + 前缀缓存是必上三件套;量化、投机解码、KV cache 进阶需评估后上。
  4. 检索层关注 HNSW ef_search 与语义缓存:这两招常能砍掉一半延迟。
  5. Agent 层控步数、小模型分流、并行工具:这是长尾延迟与成本的最大杠杆。
  6. 网络与网关异步化:被低估的延迟杀手,关 buffering、用 keep-alive、异步审计。
  7. Profiling 工具链必备:vLLM metrics + PyTorch profiler + LangSmith/Langfuse trace,生产采样、压测全开。
  8. 决策树思维:症状→瓶颈→手段,先解决工程层(ROI 高),再碰模型层。
  9. 真实案例验证:多数生产延迟问题 70% 在工程而非模型,换 GPU 前先看 trace。

性能调优是 FDE 价值最易被客户感知的环节——一个把 P95 从 10s 压到 1.5s 的动作,胜过百页 PPT。它要求的不只是技术,而是现场测量、数据驱动决策、按 ROI 排序执行的项目能力。

本专题来源

  • vLLM 官方文档与 PagedAttention 论文(Kwon et al., 2023)。
  • Anthropic Prompt Caching、OpenAI Parallel Function Calling 官方文档。
  • HNSW 原始论文(Malkov & Yashunin, 2018)及 Faiss、Milvus 调参实践。
  • LangSmith、Langfuse 官方 trace 与 observability 文档。
  • PyTorch Profiler 官方指南。
  • 现场交付项目实测数据(金融客户知识助手调优案例,2025)。
  • FDE 一线工程师关于推理层量化(AWQ/GPTQ)、投机解码(Medusa/EAGLE)的工程笔记。

本站由原始 Markdown 调研报告自动构建 · 原文未改动