Skip to content

性能测试培训 · 前沿篇

多模态 · Agent · 推理优化

1. 多模态模型架构与性能特征

多模态模型(Multimodal Model)是指能够同时理解和生成多种模态数据的AI模型,包括文本、图片、音频、视频等。相比纯文本大模型,多模态模型的性能测试面临全新的挑战。

1.1 多模态模型通用架构

输入(图/音/视频) → 模态编码器(Vision/Audio Encoder) → 跨模态对齐层(Projection) → 语言模型(LLM Backbone) → 文本/音频/图片输出

📖 架构核心思想

不同模态的数据先通过各自的编码器转换为向量表示(Embedding),再通过对齐层映射到语言模型能理解的统一空间,最终由语言模型完成理解和生成。这意味着每种模态的编码器都会引入额外的计算延迟。

主流多模态模型架构对比

模型Vision EncoderAudio EncoderLLM Backbone对齐方式
GPT-5 / GPT-5.1内置视觉编码器内置音频编码器GPT-5 系列原生融合
Claude Opus 4.x内置视觉编码器Claude 系列原生融合
Gemini 3 ProSigLIP 增强版USMGemini Decoder原生多模态
Qwen3-VLViT-bigG 升级版ParaformerQwen3-LLMCross-Attention
LLaVA(开源基线)CLIP ViT-LVicuna/Llama线性投影

说明:早期代表(GPT-4o、Claude 3.5、通义千问-VL 等)多为历史版本,2026 年主流已升级为 GPT-5、Claude Opus 4.x、Gemini 3、Qwen3-VL;LLaVA 作为开源教学基线仍具参考价值。

1.2 不同模态的Token化方式与性能影响

对性能测试人员来说,理解不同模态的Token化方式至关重要——它直接决定了推理的计算量和显存占用。

模态Token化方式典型Token数量对性能的影响
文本BPE/SentencePiece1个汉字 ≈ 1-2个Token基准,最轻量
图片Tile切分 → ViT编码256px: ~85 Tokens 1024px: ~765 Tokens 4K: ~5000+ Tokens高分辨率图片Token数暴增,TTFT显著增加
视频抽帧 → 每帧Token化10s视频(1fps): ~850 Tokens 60s视频(1fps): ~5000 Tokens 5min视频: ~25000+ Tokens超长Token序列,显存容易爆
音频梅尔频谱 → Encoder1秒音频 ≈ 25-50 Tokens 60秒音频 ≈ 1500-3000 Tokens相对轻量,但实时场景对延迟敏感

⚠️ Token数量的性能放大效应

一张4K图片可能产生5000+ Tokens,相当于一篇长文章的Token量。10并发发送4K图片 = 50000 Tokens同时涌入,对GPU显存和Prefill计算压力极大。这是多模态性能测试与纯文本性能测试最根本的差异。

1.3 多模态 vs 纯文本的性能差异

性能维度纯文本对话图片理解视频理解语音识别图片生成
TTFT200ms~1s500ms~3s2s~15s300ms~2sN/A(非流式)
Token吞吐30~80 t/s20~50 t/s10~30 t/sN/AN/A
端到端延迟2~10s3~15s10~60s0.5~5s5~120s
GPU显存基准+20~50%+100~300%+10~30%+200~500%
并发能力10~1005~502~1010~1001~5
计费按Token按Token(图片Token高)按Token(极高)按音频时长按图片数

1.4 代表产品一览

模态理解类产品生成类产品
图片GPT-5 / Claude Opus 4.x / Gemini 3 Pro / Qwen3-VLGPT-Image / Midjourney / Stable Diffusion / 即梦 / 可灵
视频Gemini 3 Pro / GPT-5 / Qwen3-VL可灵 / Runway / Sora 2 / Vidu
语音Whisper / 阿里通义听悟 / 讯飞 / Azure STTOpenAI TTS / 讯飞 / Azure TTS / ChatTTS / Fish Speech
综合GPT-5(原生多模态)/ Gemini 3 Pro(原生多模态)

课堂练习

  1. 选取你项目中使用的一个多模态模型(如GPT-5或Qwen3-VL),查阅其文档,列出它支持哪些模态以及各模态的Token计费规则
  2. 估算:发送一张1024px的图片 + 100字文本提问,总共产生多少Token?对比纯文本提问的Token数量
  3. 讨论:你的团队是否需要对多模态场景做性能测试?哪种模态是你们最常用的?

2. 图片理解性能测试

图片理解是最常见的多模态场景,用户上传一张图片让模型描述、识别文字、分析图表等。看似简单的操作背后涉及图片上传、编码、Token化、推理等多个环节。

2.1 测试场景分类

场景典型Prompt输出特征性能特点
图片描述"描述这张图片的内容"中等长度文字标准场景,作为基准
OCR文字提取"提取图片中所有文字"可能很长(取决于图中文字量)高分辨率图更准但更慢
图表数据提取"把这个表格转成JSON"结构化数据需要高分辨率才能识别
多图对比分析"对比这两张图的差异"分析性文字Token数翻倍,TTFT显著增加
物体检测/计数"图中有多少个人"简短回答推理简单但编码一样耗时
手写识别"识别手写文字内容"识别结果需要更精细的编码

2.2 图片理解的处理流程与性能瓶颈

图片上传 → 图片解码(JPEG/PNG) → 缩放/Tile切分 → Vision Encoder编码 → 跨模态对齐 → LLM推理 → 文本输出

💡 瓶颈分析

  • 图片上传:受网络带宽限制,4K图片~5MB,弱网环境可能耗时数秒
  • Vision Encoder编码:计算密集,高分辨率图片编码耗时200-1000ms
  • Prefill阶段:图片Token数量远大于文本,Prefill时间显著增加
  • 显存占用:图片Token的KV Cache占用大量显存

2.3 性能指标体系

指标定义测量方式基准参考值
图片预处理耗时上传 → 编码 → Token化服务端日志或API响应中的耗时字段100~500ms
TTFT(含图片编码)发送请求到首Token客户端SSE计时500ms~3s
总响应时间发送到完整回答客户端计时3~15s
分辨率-性能系数不同分辨率下的性能差异控制变量对比4K约为256px的3-5倍
格式-性能差异JPEG/PNG/WebP/HEIC差异相同内容不同格式对比通常差异<10%
多图性能退化图片数量增加时的性能变化1/5/10/20张图片对比接近线性退化

2.4 不同分辨率的性能影响

分辨率估算Token数TTFT (1并发)总响应时间显存增量
256×256~85~400ms~3s+50MB
512×512~340~600ms~4s+150MB
1024×1024~765~1s~6s+400MB
2048×2048~3000~2s~10s+1.5GB
4K (3840×2160)~5500~3.5s~15s+3GB

2.5 不同图片格式的性能差异

格式文件大小(1024px)解码速度API支持度推荐度
JPEG~150KB全平台支持推荐
PNG~800KB全平台支持推荐
WebP~100KB大部分支持推荐
HEIC~120KB部分支持需验证
BMP~3MB快(无压缩)部分支持不推荐
Base64编码原始×1.33需额外解码全平台支持体积增大

2.6 多图场景的性能影响

图片数量 vs 性能退化(1024px JPEG,GPT-4o):

图片数    Token数    TTFT       总响应时间    显存增量
1张       ~800      ~1s        ~5s          +400MB
3张       ~2400     ~2s        ~8s          +1.2GB
5张       ~4000     ~3s        ~12s         +2GB
10张      ~8000     ~5s        ~20s         +4GB
20张      ~16000    ~10s       ~35s         +8GB

结论:
  → Token数与图片数接近线性关系
  → TTFT增长比线性更快(Prefill计算量是O(n²)级别)
  → 超过10张图片时性能显著恶化

2.7 完整测试用例表

用例ID场景输入关注指标PASS标准
IMG-01单图描述(低分辨率)256px JPEG + "描述这张图"TTFT / E2ETTFT P95 < 1s, E2E P95 < 5s
IMG-02单图描述(高分辨率)1024px JPEG + "描述这张图"TTFT / E2ETTFT P95 < 2s, E2E P95 < 10s
IMG-03单图描述(4K)4K JPEG + "描述这张图"TTFT / 显存TTFT P95 < 5s, 无OOM
IMG-04OCR文字提取含密集文字的文档图片E2E / 准确性E2E P95 < 15s
IMG-05图表数据提取Excel截图 + "转为JSON"E2E / 输出完整性E2E P95 < 15s
IMG-06多图对比(2张)两张1024px图 + "对比差异"TTFT / E2ETTFT P95 < 3s
IMG-07多图对比(5张)五张1024px图 + "总结共同点"TTFT / 显存TTFT P95 < 6s, 无OOM
IMG-08多图对比(10张)十张1024px图 + "逐一描述"TTFT / E2E / 显存TTFT P95 < 10s
IMG-09不同格式对比同图JPEG/PNG/WebP + 相同PromptTTFT差异格式间差异 < 20%
IMG-10并发图片请求10并发 × 1024px图片TTFT / 错误率 / 显存错误率 < 1%, 无OOM
IMG-11Base64 vs URL同图Base64编码 vs URL引用请求耗时差异记录差异即可
IMG-12超大图片边界10MB+ 图片是否被拒绝/自动压缩有合理处理(非500错误)

2.8 压测方法:构造多图并发请求

python
import asyncio
import httpx
import base64
import time
from pathlib import Path

async def image_benchmark(image_paths: list[str], prompt: str, concurrency: int):
    """多图并发图片理解压测"""
    
    def encode_image(path: str) -> str:
        with open(path, "rb") as f:
            return base64.b64encode(f.read()).decode()
    
    images_b64 = [encode_image(p) for p in image_paths]
    
    async def single_request(client, img_b64):
        content = [
            {"type": "text", "text": prompt},
            {"type": "image_url", "image_url": {
                "url": f"data:image/jpeg;base64,{img_b64}",
                "detail": "high"
            }}
        ]
        payload = {
            "model": "gpt-4o",
            "messages": [{"role": "user", "content": content}],
            "stream": True, "max_tokens": 300
        }
        t0 = time.perf_counter()
        ttft = None
        async with client.stream("POST", "/v1/chat/completions",
                                  json=payload) as resp:
            async for line in resp.aiter_lines():
                if line.startswith("data: ") and line[6:] != "[DONE]":
                    if ttft is None:
                        ttft = (time.perf_counter() - t0) * 1000
        total = (time.perf_counter() - t0) * 1000
        return {"ttft_ms": ttft, "total_ms": total}
    
    sem = asyncio.Semaphore(concurrency)
    async def worker(client, img):
        async with sem:
            return await single_request(client, img)
    
    headers = {"Authorization": "Bearer sk-xxx"}
    async with httpx.AsyncClient(
        base_url="https://api.openai.com",
        headers=headers, timeout=120
    ) as client:
        tasks = [worker(client, img) for img in images_b64]
        results = await asyncio.gather(*tasks)
    return results

⚠️ 费用提醒

图片理解的Token消耗远大于文本!一张1024px高清图片约765 Tokens,相当于一篇500字文章。10并发 × 20张图片 = 约15,000图片Tokens,加上文本和输出,一轮压测可能消耗几万Token。务必先算好预算!

课堂练习

  1. 准备3张不同分辨率(256/1024/4K)的测试图片,分别测量TTFT和总响应时间,画出分辨率-延迟曲线
  2. 用同一张图片分别以JPEG、PNG、WebP格式上传,对比性能差异
  3. 测试多图场景:发送1/3/5/10张图片,观察TTFT的增长趋势
  4. 计算你的项目中图片理解场景一次压测(10并发×5分钟)的预估费用

3. 图片生成性能测试

图片生成与图片理解在性能特征上截然不同——它不是流式返回的,而是一次性返回完整图片。生成时间可以从几秒到几分钟不等。

3.1 代表产品与API

产品/模型类型典型生成时间API可用性计费方式
DALL-E 3API服务10~30s公开API按图片数量
MidjourneySaaS服务30~120s非官方API按订阅
Stable Diffusion (自部署)自部署5~60s完全控制GPU成本
可灵API服务15~60s公开API按图片数量
Flux自部署/API10~40s公开API按图片数量

3.2 图片生成流程

文本Prompt → 文本编码(CLIP) → 扩散模型推理(N步) → 图片解码(VAE) → 后处理/安全检查 → 返回图片

📖 与文本生成的本质区别

  • 非流式:文本生成可以逐Token流式返回,图片生成必须等所有扩散步骤完成后一次性返回
  • 无TTFT概念:用户必须等到整张图片生成完毕才能看到结果
  • GPU显存占用极高:生成1024px图片可能需要6~10GB显存,远超文本推理
  • 计算密集型:扩散模型需要反复迭代(20~100步),每步都是完整的前向传播

3.3 性能指标

指标定义影响因素典型值
生成延迟从提交Prompt到返回图片的总时间图片尺寸、步数、模型5~120s
并发生成能力同时能处理几个生成请求GPU显存和数量1~8(单卡)
GPU显存峰值生成过程中的最大显存占用图片尺寸、batch size6~24GB
每秒迭代步数(it/s)扩散模型每秒完成的迭代步数GPU算力、模型大小1~10 it/s

3.4 不同参数组合的性能对比

参数组合生成时间(A100)显存占用图片质量
SD1.5, 512px, 20步~3s~4GB基础
SD1.5, 512px, 50步~7s~4GB良好
SDXL, 1024px, 30步~12s~8GB很好
SDXL, 1024px, 50步~18s~8GB优秀
SD3, 1024px, 28步~15s~10GB优秀
Flux, 1024px, 20步~20s~12GB顶级
SDXL, 2048px, 50步~50s~16GB优秀(超高清)

3.5 自部署 vs API调用的性能测试差异

维度自部署(Stable Diffusion)API调用(DALL-E 3)
可控性完全控制参数、步数、采样器只能控制尺寸、质量等有限参数
并发上限由GPU数量决定由API配额决定
性能瓶颈GPU计算和显存API限流和网络
压测方法GPU监控 + 并发阶梯加压限流探测 + 排队监控
费用GPU租赁/购买成本按图片数量付费

3.6 测试用例表

用例ID场景输入参数关注指标PASS标准
GEN-01基础生成(512px)短Prompt, 512px, 20步生成延迟延迟 < 10s
GEN-02高质量生成(1024px)长Prompt, 1024px, 50步生成延迟延迟 < 30s
GEN-03超高清生成(2048px)1024px, 50步延迟 / 显存延迟 < 60s, 无OOM
GEN-04并发生成(2并发)2个同时请求各自延迟 / 显存延迟 < 单请求×1.5
GEN-05并发生成(5并发)5个同时请求排队 / OOM无OOM, 排队透明
GEN-06批量生成(10张)连续提交10个请求总耗时 / 平均延迟总耗时合理
GEN-07不同步数对比20/30/50/100步延迟随步数的变化接近线性增长
GEN-08不同尺寸对比512/768/1024/2048延迟随尺寸的变化记录变化趋势

课堂练习

  1. 选择一个图片生成API(DALL-E 3或自部署SD),测量不同尺寸下的生成延迟
  2. 如果是自部署模型,用nvidia-smi监控生成过程中的GPU显存变化,找出显存峰值
  3. 测试并发能力:逐步增加并发数(1→2→3→5),找出单卡GPU的并发上限
  4. 对比不同步数(20/50)对生成延迟的影响,计算每增加一步的边际延迟

4. 视频理解性能测试

视频理解是多模态中计算量最大的场景——一段60秒的视频经过抽帧和编码后可以产生数千甚至数万个Token,对GPU显存和推理时间提出极大挑战。

4.1 视频理解处理流程

视频上传 → 视频解码 → 抽帧(采样策略) → 每帧Vision Encoder编码 → 时序建模 → LLM推理 → 文本输出

4.2 关键性能瓶颈

抽帧策略对性能和质量的影响

抽帧策略帧数(60s视频)Token数编码时间理解质量
每秒1帧(1fps)60帧~5000~5s基本够用
每秒5帧(5fps)300帧~25000~20s动作细节好
关键帧检测10~30帧~1000~2500~2s场景变化好,连续动作差
均匀采样8帧8帧~700~0.5s粗略概览

⚠️ 视频Token数量的爆炸性增长

视频参数 → Token数量估算:

10秒视频, 1fps, 720p:   10帧 × ~300 tokens/帧 = ~3,000 tokens
60秒视频, 1fps, 720p:   60帧 × ~300 tokens/帧 = ~18,000 tokens
5分钟视频, 1fps, 720p: 300帧 × ~300 tokens/帧 = ~90,000 tokens ← 接近上下文窗口极限!
30分钟视频, 1fps, 720p: 无法直接处理 → 必须分段

对比:一篇3000字文章 ≈ ~5000 tokens
      一段60秒视频   ≈ ~18000 tokens = 3.6倍

4.3 视频时长 × 分辨率 × 帧率的性能矩阵

视频参数Token估算TTFT总响应时间显存需求
10s, 480p, 1fps~1,500~2s~8s+1GB
10s, 1080p, 1fps~3,000~3s~12s+2GB
60s, 720p, 1fps~12,000~8s~30s+6GB
60s, 1080p, 1fps~18,000~12s~45s+10GB
5min, 720p, 1fps~60,000~30s~120s+30GB
30min, 720p, 1fps~360,000超出窗口需分段处理不可行

4.4 长视频分段处理策略

方案A:滑动窗口法
  将30分钟视频切分为6段×5分钟
  每段独立理解 → 最后汇总
  优点:简单可靠
  缺点:段间信息丢失,汇总需要额外LLM调用

方案B:层次化摘要
  全视频低帧率(0.2fps)粗览 → 生成时间线
  关键片段高帧率(5fps)精读 → 详细分析
  优点:效率高
  缺点:实现复杂

方案C:音频+关键帧
  提取音频转文字(ASR) → 关键帧采样 → 结合分析
  优点:信息损失少
  缺点:多模态流水线,任意环节可能瓶颈

4.5 测试用例表

用例ID场景视频参数关注指标PASS标准
VID-01短视频理解10s, 720pTTFT / E2ETTFT < 5s, E2E < 15s
VID-02中等视频理解60s, 720pTTFT / E2E / 显存TTFT < 15s, E2E < 60s
VID-03长视频理解5min, 720pE2E / 是否超时能完成或合理分段
VID-04高清视频理解10s, 1080pTTFT / 与720p对比记录差异
VID-054K视频理解10s, 4KTTFT / 显存 / OOM无OOM
VID-06并发视频请求3并发 × 10s视频各自延迟 / 显存无OOM, 错误率<1%
VID-07不同抽帧策略对比同视频, 1fps vs 关键帧延迟 vs 质量记录差异
VID-08超长视频边界30min视频系统行为合理拒绝或自动分段

课堂练习

  1. 准备3段不同时长(10s/60s/5min)的测试视频,测量各自的处理时间
  2. 对比不同抽帧策略(1fps vs 关键帧)的性能和理解质量差异
  3. 尝试发送超长视频(超过模型上下文窗口),观察系统如何处理
  4. 如果是自部署模型,在处理视频时监控GPU显存变化趋势

5. 视频生成性能测试

视频生成是当前AI中计算量最大、耗时最长的任务。一段5秒的视频可能需要数分钟甚至数十分钟来生成,对GPU资源的消耗远超其他任何模态。

5.1 代表产品

产品典型生成时间最大视频时长最高分辨率接入方式
可灵2~10min~10s1080pAPI
Runway Gen-31~5min~10s1080pAPI
Sora5~20min~60s1080p受限API
Pika1~3min~4s1080pAPI
Stable Video Diffusion(自部署)3~15min~4s1024px自部署

5.2 视频生成流程特殊性

提交生成请求 → 进入排队 → 扩散模型推理(逐帧) → 时序一致性后处理 → 视频编码 → 安全审核 → 可下载

💡 异步任务模型

几乎所有视频生成服务都采用异步任务模型:提交请求后返回task_id,客户端需要定期轮询状态,直到任务完成后下载结果。这与文本/图片理解的同步请求-响应模式完全不同。

1. POST /api/video/generate → 返回 { "task_id": "abc123", "status": "queued" }
2. GET  /api/video/status/abc123 → { "status": "processing", "progress": 45 }
3. GET  /api/video/status/abc123 → { "status": "completed", "video_url": "..." }
4. GET  视频下载URL → 二进制视频文件

5.3 性能指标

指标定义典型值说明
排队等待时间提交到开始生成0~30min取决于平台负载
实际生成时间开始生成到完成1~20min核心指标
生成比生成时间 / 视频时长10x~100x生成5s视频可能需要5min
总端到端时间提交到可下载2~30min排队+生成+后处理
并发任务数平台同时处理的任务数1~3(单用户)通常有严格限制
GPU消耗单个生成任务的GPU资源24~80GB显存远超文本和图片

5.4 不同参数的性能影响

参数选项对生成时间的影响对质量的影响
视频时长2s / 5s / 10s接近线性增长越长越容易不一致
分辨率480p / 720p / 1080p1080p约为480p的3-5倍更清晰
帧率8fps / 24fps / 30fps30fps约为8fps的3倍更流畅
风格写实 / 动画 / 电影影响较小(~10%)风格化差异

5.5 并发测试的特殊性

⚠️ 视频生成并发数极低

不要用文本/图片理解的并发思维来压测视频生成!

文本对话:50并发是正常起步
图片理解:10-20并发可以做
图片生成:5-10并发已经不小
视频生成:1-3并发就是极限(单用户配额)

视频生成压测的重点不是"高并发",而是:
  → 排队机制是否合理
  → 任务状态轮询是否可靠
  → 长时间等待后是否能正常返回
  → 多个用户同时提交时的公平调度

5.6 测试用例表

用例ID场景输入参数关注指标PASS标准
VGEN-01短视频生成"一只猫在走路", 2s, 720p总耗时< 5min
VGEN-02中等视频生成详细描述, 5s, 1080p总耗时< 10min
VGEN-03长视频生成详细描述, 10s, 1080p总耗时< 20min
VGEN-04并发提交(2个)同时提交2个请求排队/并行合理排队或并行
VGEN-05并发提交(5个)同时提交5个请求排队顺序/公平性先到先处理
VGEN-06轮询可靠性提交后持续轮询状态状态变化正确性queued→processing→completed
VGEN-07超时场景提交后等待30min是否有超时机制有合理的超时和通知
VGEN-08取消任务生成中取消是否能成功取消能取消且释放资源

课堂练习

  1. 选择一个视频生成API,测量从提交到完成的全流程耗时,区分排队时间和生成时间
  2. 同时提交2个生成请求,观察是串行排队还是并行处理
  3. 编写一个轮询脚本,每5秒查询一次任务状态,记录完整的状态变化时间线
  4. 计算你的视频生成场景的"生成比"(生成时间/视频时长),评估是否满足业务需求

6. 语音识别(ASR)性能测试

语音识别(ASR, Automatic Speech Recognition)将音频转为文字,是AI语音交互的基础能力。与文本和图片不同,ASR有独特的实时性要求——处理速度必须跟上甚至快于说话速度。

6.1 ASR Pipeline

音频输入 → 预处理(降噪/VAD) → 特征提取(梅尔频谱) → 模型推理 → 解码/后处理 → 文本输出

6.2 代表产品/模型

产品/模型类型支持语种实时性特点
Whisper (OpenAI)API/自部署99种语言离线为主准确率高,多语种
Whisper large-v3自部署99种语言离线/流式开源可部署
阿里达摩院 ParaformerAPI/自部署中英实时中文效果好
讯飞ASRAPI中英+方言实时方言支持好
Azure SpeechAPI100+语言实时企业级稳定

6.3 核心性能指标

指标定义计算公式合格标准
实时率(RTF)处理1秒音频需要多少秒处理时间 / 音频时长RTF < 1.0(才能实时)
首字延迟流式场景从开始发送到第一个字t(首字) - t(发送)< 500ms
端到端延迟整段音频从提交到全部文字返回t(完成) - t(提交)< 音频时长 × 1.5
字错率(WER)识别错误率(功能指标)(S+D+I) / N< 5%(安静环境中文)

📐 RTF(Real-Time Factor)详解

RTF = 处理时间 / 音频时长

RTF = 0.1: 处理1秒音频只需0.1秒 → 非常快,有余量
RTF = 0.5: 处理1秒音频需要0.5秒 → 快于实时,可以做流式
RTF = 1.0: 处理1秒音频需要1.0秒 → 刚好实时,无余量
RTF = 2.0: 处理1秒音频需要2.0秒 → 慢于实时,只能离线

要求:
  → 离线转写场景:RTF < 1.0 即可
  → 实时字幕场景:RTF < 0.3(需要余量处理网络抖动)
  → 实时对话场景:RTF < 0.2(用户等不起)

6.4 不同音频参数的性能影响

参数选项对性能的影响推荐选择
采样率8kHz / 16kHz / 44.1kHz8k最快但质量差,16k平衡,44.1k数据量大但边际提升小16kHz
编码格式WAV / MP3 / AAC / OGGWAV无压缩最快解码,MP3需解码但文件小16kHz 16bit WAV
通道数单声道 / 立体声立体声数据量翻倍但ASR通常只需单声道单声道
音频时长1s / 10s / 60s / 5min接近线性增长(离线模式)分段处理长音频

6.5 不同场景的性能差异

场景典型RTF典型WER说明
安静环境 + 普通话0.1~0.32~5%最佳场景
安静环境 + 英语0.1~0.33~8%取决于口音
嘈杂环境(SNR 10dB)0.2~0.48~15%预处理增加延迟
多人说话(重叠)0.3~0.515~30%需要说话人分离
口音/方言0.2~0.410~25%需要专用模型
电话音质(8kHz)0.1~0.25~12%低采样率影响质量

6.6 流式ASR vs 离线ASR

维度流式ASR离线ASR
使用场景实时字幕、语音输入、客服录音转写、会议纪要
关键指标首字延迟、RTF总处理时间、WER
数据发送音频边录制边发送(WebSocket)完整音频文件一次上传
结果返回逐句/逐字实时返回全部处理完一次性返回
准确率略低(缺少后文上下文)更高(有完整上下文)
压测重点首字延迟、WebSocket连接数RTF、并发处理能力

6.7 测试用例表

用例ID场景输入参数关注指标PASS标准
ASR-01短音频识别5s, 16kHz, WAV, 普通话RTF / E2ERTF < 0.5
ASR-02中等音频识别60s, 16kHz, WAV, 普通话RTF / E2ERTF < 0.5
ASR-03长音频识别5min, 16kHz, WAVRTF / 是否分段RTF < 1.0
ASR-04不同采样率对比同内容, 8k/16k/44.1kRTF和WER差异记录差异
ASR-05不同编码格式对比同内容, WAV/MP3/AACRTF差异格式间差异 < 30%
ASR-06嘈杂环境带噪音音频, SNR 10dBRTF / WERWER < 15%
ASR-07多语种中文/英文/日文RTF / WER per lang各语种WER合理
ASR-08并发请求(10)10并发 × 10s音频RTF / 错误率RTF < 1.0, 错误率 < 1%
ASR-09流式ASR首字延迟WebSocket + 边发边识别首字延迟首字 < 500ms
ASR-10流式ASR连接数50/100/200 WebSocket连接连接成功率成功率 > 99%

课堂练习

  1. 准备不同时长(5s/30s/60s)的测试音频,分别测量RTF,验证是否满足实时性要求
  2. 用同一段音频分别以WAV和MP3格式上传,对比处理时间差异
  3. 如果有流式ASR接口,测量WebSocket连接的首字延迟
  4. 在不同并发(1/5/10/20)下测试离线ASR的RTF变化趋势

7. 语音合成(TTS)性能测试

语音合成(TTS, Text-To-Speech)将文字转化为语音。在AI对话场景中,TTS的性能直接影响用户的"听觉体验"——如果合成速度慢于播放速度,用户就会听到断断续续的语音。

7.1 TTS Pipeline

文本输入 → 文本分析(分句/韵律) → 声学模型(生成频谱) → 声码器(频谱→波形) → 后处理(增益/降噪) → 音频输出

7.2 代表产品/模型

产品/模型类型流式支持音色数量特点
OpenAI TTSAPI支持6种自然度高,多语种
Azure TTSAPI支持400+企业级,SSML支持
讯飞TTSAPI支持100+中文效果好
ChatTTS自部署支持可克隆对话式TTS,开源
Fish Speech自部署支持可克隆零样本克隆,开源
Bark自部署部分有限可生成非语音声音

7.3 核心性能指标

指标定义计算方式合格标准
首字节延迟发送文本到收到第一段音频t(首音频) - t(请求)< 300ms (流式TTS)
合成速度比每秒生成多少秒音频音频时长 / 合成时间> 2.0x(至少2倍速)
端到端延迟全部文本转为全部音频的时间t(完成) - t(请求)< 文本朗读时长
音频质量(MOS)主观听感评分(1~5分)人工评测或客观指标> 4.0

💡 流式TTS的关键约束:合成速度必须快于播放速度

场景:用户在听AI的语音回复

播放速度 = 1.0x(正常语速)
合成速度 > 1.0x → 正常,音频数据缓冲区持续增长
合成速度 = 1.0x → 刚好,一旦网络抖动就会卡顿
合成速度 < 1.0x → 必然卡顿!用户听到"一句...停...一句...停..."

推荐:合成速度 > 2.0x,预留足够缓冲应对网络和计算波动

7.4 不同参数的性能影响

参数选项对延迟的影响对质量的影响
文本长度10字 / 100字 / 500字 / 2000字接近线性增长无显著影响
语速0.5x / 1.0x / 1.5x / 2.0x快语速合成更快过快可能失真
音色不同speaker影响较小(< 10%)因音色而异
情感中性 / 高兴 / 悲伤 / 严肃可能增加10~20%更自然
采样率16kHz / 24kHz / 44.1kHz高采样率略慢高采样率更清晰

7.5 测试用例表

用例ID场景输入关注指标PASS标准
TTS-01短文本合成"你好,有什么可以帮你?"首字节延迟< 300ms
TTS-02中等文本合成100字段落合成速度比> 2.0x
TTS-03长文本合成1000字文章E2E延迟 / 合成速度合成速度 > 2.0x
TTS-04流式TTS边收到文字边合成首字节延迟 / 卡顿率首字节 < 300ms, 无卡顿
TTS-05不同语速对比同文本, 0.5x/1.0x/2.0x合成速度差异记录差异
TTS-06并发合成(10)10并发 × 短文本合成速度/错误率合成速度 > 1.5x
TTS-07并发合成(50)50并发 × 短文本合成速度/错误率合成速度 > 1.0x
TTS-08多音色对比同文本, 不同音色延迟差异音色间差异 < 20%

课堂练习

  1. 选择一个TTS API,测量不同文本长度(10字/100字/1000字)下的合成速度比
  2. 测试流式TTS的首字节延迟,确认是否满足实时对话需求
  3. 在不同并发数下测试合成速度的变化,找到"合成速度 < 播放速度"的并发拐点
  4. 如果你的场景是LLM输出文字+TTS播报,测量"LLM首Token → TTS首音频"的端到端延迟

8. 多模态综合场景

真实业务中,往往不会只用到单一模态。多种模态组合在一起,性能问题会变得更加复杂——任何一个环节的延迟都会影响整体体验。

8.1 场景1:图片+文字混合对话

用户发文字 → AI回复文字 → 用户发图片+文字 → AI理解图片并回复 → 用户追问 → AI结合图片上下文回答

📖 性能挑战

  • 第3轮发送图片时,上下文包含前面2轮的文本 + 新图片的Token,总Token数激增
  • 第5轮追问时,上下文包含了前面所有轮次的内容(含图片Token),TTFT会显著增加
  • 多轮对话中图片Token不会被"遗忘",一直占用上下文窗口
对话轮次内容累积Token估算TTFT预期
第1轮纯文字提问~100~300ms
第2轮纯文字追问~300~400ms
第3轮发送1024px图片~1100 (+800图片)~1.2s
第4轮追问图片内容~1400~1.5s
第5轮发送第2张图片~2200 (+800图片)~2.5s
第8轮总结所有内容~3500~4s

8.2 场景2:语音实时对话

用户语音输入 → ASR转文字 → LLM理解+生成 → TTS合成语音 → 播放给用户

⚠️ 端到端延迟要求极其严格

用户说完话 → 听到AI回复 的总延迟分解:

  ASR 处理:    200~500ms (流式ASR尾部延迟)
  LLM TTFT:    300~1000ms
  TTS 首音频:  200~500ms
  ──────────────────────
  总计:        700~2000ms

人类对话的自然停顿 ≈ 500~1500ms
如果AI回复延迟 > 2s → 感觉像在"等对方思考"
如果AI回复延迟 > 4s → 用户会怀疑系统卡了

优化关键:三个环节流水线并行!
  → ASR边识别边传给LLM(流式ASR)
  → LLM边生成边传给TTS(流式LLM + 流式TTS)
  → 总延迟 ≈ ASR尾部 + LLM TTFT + TTS首字节 ≈ 最快700ms

8.3 场景3:视频分析 → 文字报告 → 语音播报

上传视频 → 视频理解(VLM) → 生成文字报告(LLM) → 语音播报(TTS)

环节典型耗时(60s视频)瓶颈风险
视频上传2~10s (取决于网络)大文件上传
视频理解15~45s主瓶颈
文字报告生成5~15s可流式减少感知
TTS合成3~10s可流式播放
总计25~80s

8.4 场景4:多模态Agent

场景:AI助手看屏幕截图 → 分析当前状态 → 执行操作

步骤:
  1. 截取屏幕截图 → ~100ms
  2. 图片理解(分析当前界面)→ ~2s
  3. LLM决定下一步操作 → ~1s
  4. 执行操作(点击/输入)→ ~500ms
  5. 等待界面变化 → 1~3s
  6. 再截图 → 回到步骤2

  一轮循环 ≈ 5~7s
  完成一个复杂任务(10步)≈ 50~70s

性能挑战:
  → 每步都有图片编码开销
  → 上下文中累积大量截图Token
  → 操作失败需要重试,耗时翻倍

8.5 综合压测方案

TIP

多模态综合压测方案模板
════════════════════════════════════════

流量分配:
  图文混合对话    40%
  语音对话        25%
  视频分析        10%
  图片生成        15%
  纯文本对话      10%

并发设置(总10并发):
  图文对话: 4并发
  语音对话: 3并发(ASR+LLM+TTS三级联)
  视频分析: 1并发(资源消耗最大)
  图片生成: 1并发(GPU显存限制)
  纯文本: 1并发(基准对照)

GPU资源监控:
  每5秒记录 GPU利用率/显存/温度
  特别关注显存峰值(多模态并发容易OOM)

阶梯加压:
  总并发 5 → 10 → 15 → 20
  每级持续5分钟

8.6 测试用例表

用例ID场景关注指标PASS标准
MM-015轮图文混合对话各轮TTFT退化曲线第5轮TTFT < 5s
MM-02语音实时对话(5轮)端到端语音延迟延迟 < 2s
MM-03视频分析+文字+播报端到端总耗时60s视频 < 90s处理
MM-04多模态Agent(5步)单步延迟 / 总耗时总耗时 < 40s
MM-05混合流量综合压测各场景达标率所有场景P95达标
MM-06模态切换延迟从文字切到图片的额外延迟切换开销 < 500ms

课堂练习

  1. 设计一个5轮图文混合对话测试,记录每轮的TTFT变化
  2. 如果你的系统支持语音对话,测量"说完话→听到回复"的端到端延迟
  3. 构造一个多模态级联场景(如视频分析→报告→播报),测量各环节耗时占比
  4. 做一次综合压测,观察不同模态并发时GPU显存是否会溢出

9. Agent 执行模式与性能模型

AI Agent是当前大模型应用中最复杂的场景——一个用户请求可能触发数十次LLM调用和工具调用,性能问题被成倍放大。

9.1 Agent的本质

📖 Agent = 多次 LLM 调用 + 多次工具调用 的循环

与普通对话的"一问一答"不同,Agent需要自主思考、规划、执行、观察,直到完成任务。每一步都是一次LLM推理,每次工具使用都是一次外部调用。这些调用串联起来,形成一条长链路。

9.2 三种执行模式

模式1:ReAct(Reasoning + Acting)

循环结构:
  思考(Thought) → 行动(Action) → 观察(Observation) → 思考 → ...

示例:"帮我查北京明天的天气,如果下雨就提醒我带伞"
  Step 1: 思考 → 需要查天气 → 调用 get_weather("北京","明天")
  Step 2: 观察 → 明天小雨
  Step 3: 思考 → 下雨了,需要提醒带伞
  Step 4: 行动 → 生成回复

特点:每步动态决策,灵活但可能步数不确定

模式2:Plan-and-Execute

两阶段结构:
  规划阶段 → 生成所有步骤的计划
  执行阶段 → 逐步执行计划中的步骤

示例:"帮我订明天飞上海的机票"
  Plan: 1.查航班 2.筛选价格 3.选座位 4.下单 5.确认
  Execute: 依次执行每一步

特点:步骤确定,可预测,但不够灵活

模式3:混合模式

结构:先规划 → 执行时可动态调整

示例:先制定大框架,执行中遇到意外时调整计划
  Plan: 1.查航班 2.选座 3.下单
  Execute Step 1: 查航班 → 发现航班取消
  Re-Plan: 1.改查高铁 2.选座 3.下单
  Execute Step 1: 查高铁 → 找到班次
  ...

特点:兼顾可预测性和灵活性

9.3 Agent的性能放大效应

⚠️ Agent性能的"冰山效应"

用户看到的:发了1个请求 → 等了30秒 → 收到回复

水面下实际发生的:
  LLM调用 #1: 理解用户意图            3s
  LLM调用 #2: 决定调用什么工具         2s
  工具调用 #1: 查询数据库              0.5s
  LLM调用 #3: 分析查询结果            2s
  LLM调用 #4: 决定还需要什么信息       2s
  工具调用 #2: 调用外部API             1.5s
  工具调用 #3: 计算汇总               0.3s
  LLM调用 #5: 生成最终回复            4s
  ─────────────────────────────────
  总计: 5次LLM调用 + 3次工具调用 ≈ 15.3s + 开销 ≈ 18s

放大效应公式:
  Agent_latency = Σ(LLM_calls × avg_LLM_time) + Σ(Tool_calls × avg_Tool_time) + overhead

  其中 overhead 包括:上下文拼接、结果解析、日志记录等

9.4 Agent vs 普通对话的性能对比

维度普通对话Agent(简单任务)Agent(复杂任务)
LLM调用次数12~35~20
工具调用次数0~11~33~15
放大系数1~23~68~35
端到端延迟2~10s10~30s30s~5min
Token消耗100~20002000~1000010000~100000
10并发的内部压力10次LLM调用30~60次80~350次

💡 关键洞察

10个并发用户使用Agent,对LLM的实际压力可能等于100~350次并发LLM调用。在做Agent性能测试时,必须考虑这个放大效应来评估后端服务的承载能力。

课堂练习

  1. 分析你项目中的Agent场景,画出一个典型任务的完整调用链路图(含每步的LLM调用和工具调用)
  2. 计算一个典型Agent任务的放大系数:总共多少次LLM调用 + 工具调用?
  3. 根据放大系数,估算10并发用户对后端LLM服务的实际压力
  4. 讨论:你的Agent使用的是哪种执行模式(ReAct/Plan-and-Execute/混合)?各有什么性能优劣?

10. ReAct 链路性能分析

ReAct是最常见的Agent执行模式。每一步都包含"思考→行动→观察"三个阶段,理解每步的耗时分布是优化Agent性能的基础。

10.1 ReAct单步耗时分解

阶段做什么典型耗时瓶颈原因
ThinkingLLM推理,决定下一步1~5s模型大小、上下文长度
Action执行工具调用0.1~30s工具本身的延迟差异极大
Observation接收工具结果,解析0.1~1s结果数据量、解析复杂度
上下文拼接将结果追加到上下文~10ms通常不是瓶颈

10.2 典型ReAct任务的性能Profile

简单任务(2-3步):查天气+推荐穿搭
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1: Think(2s) → get_weather(0.5s) → Observe(0.2s)     = 2.7s
Step 2: Think(2s) → generate_response(3s)                  = 5.0s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总耗时: ~8s    LLM调用: 2次    工具调用: 1次

中等任务(5-8步):帮我订酒店
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1: Think(2s) → search_hotels(2s)     → Observe(0.3s)  = 4.3s
Step 2: Think(3s) → filter_by_price(0.5s) → Observe(0.2s)  = 3.7s
Step 3: Think(2s) → get_reviews(1.5s)     → Observe(0.3s)  = 3.8s
Step 4: Think(3s) → check_availability(1s)→ Observe(0.2s)  = 4.2s
Step 5: Think(2s) → book_room(2s)         → Observe(0.3s)  = 4.3s
Step 6: Think(3s) → generate_response(4s)                   = 7.0s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总耗时: ~27s   LLM调用: 6次    工具调用: 5次

复杂任务(10+步):分析数据并生成报告
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1-3:  数据查询(3步)                                    ~12s
Step 4-6:  数据分析(3步)                                    ~15s
Step 7-8:  生成图表(2步)                                    ~10s
Step 9-10: 汇总报告(2步)                                    ~12s
Step 11:   格式化输出                                          ~5s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总耗时: ~54s   LLM调用: 11次   工具调用: 8次

10.3 性能测试关注点

上下文递增导致的性能退化

⚠️ 关键问题:随着步数增加,每步LLM推理越来越慢!

原因:每步的思考都需要把之前所有步骤的上下文发给LLM

Step 1: 上下文 ~500 tokens  → Think 1.5s
Step 3: 上下文 ~2000 tokens → Think 2.5s
Step 5: 上下文 ~5000 tokens → Think 3.5s
Step 8: 上下文 ~10000 tokens → Think 5.0s
Step 10: 上下文 ~15000 tokens → Think 7.0s

后面步骤的TTFT可能是前面的3~5倍!
如果工具返回了大量数据(如完整SQL结果),上下文膨胀更快

死循环检测

常见死循环模式:
  Think → 调用工具A → 结果不满意 → Think → 又调用工具A → ...
  Think → 决定重新规划 → Think → 又决定重新规划 → ...

性能影响:
  → Token无限消耗(费用爆炸)
  → 连接长时间占用
  → 用户无限等待

检测方法:
  → 设置最大步数限制(如20步)
  → 检测连续N步是否在调用相同工具+相同参数
  → 总执行时间超过阈值(如5分钟)强制终止

10.4 测试方法:注入计时点,生成瀑布图

python
import time
import json

class ReActProfiler:
    def __init__(self):
        self.steps = []
    
    def record_step(self, step_num, phase, start, end, detail=""):
        self.steps.append({
            "step": step_num,
            "phase": phase,
            "start_ms": round(start * 1000, 2),
            "end_ms": round(end * 1000, 2),
            "duration_ms": round((end - start) * 1000, 2),
            "detail": detail
        })
    
    def print_waterfall(self):
        """生成瀑布图(文本版)"""
        if not self.steps:
            return
        t0 = self.steps[0]["start_ms"]
        for s in self.steps:
            offset = s["start_ms"] - t0
            bar_len = int(s["duration_ms"] / 100)
            bar = "█" * max(bar_len, 1)
            spaces = " " * int(offset / 100)
            print(f"  Step{s['step']:2d} {s['phase']:12s} "
                  f"{spaces}{bar} {s['duration_ms']:.0f}ms "
                  f"{s['detail']}")

profiler = ReActProfiler()

async def react_step(step_num, context):
    t0 = time.perf_counter()
    thought = await llm_call(context)
    t1 = time.perf_counter()
    profiler.record_step(step_num, "Think", t0, t1)
    
    if thought.needs_tool:
        t2 = time.perf_counter()
        result = await call_tool(thought.tool, thought.args)
        t3 = time.perf_counter()
        profiler.record_step(step_num, "Action", t2, t3, thought.tool)
        
        t4 = time.perf_counter()
        context = parse_and_append(context, result)
        t5 = time.perf_counter()
        profiler.record_step(step_num, "Observe", t4, t5)
    
    return context, thought.is_done

10.5 测试用例表

用例ID场景预期步数关注指标PASS标准
REACT-01简单查询(2步)2~3总耗时 / 每步耗时总耗时 < 15s
REACT-02中等任务(5步)4~6上下文退化 / 总耗时总耗时 < 45s
REACT-03复杂任务(10步)8~12退化曲线 / 总耗时总耗时 < 2min
REACT-04工具失败重试增加1~3步重试耗时 / 最终结果重试后能完成
REACT-05死循环检测触发步数上限是否检测到循环在20步内终止
REACT-06并发Agent(5)各3~5步各Agent延迟/相互影响互不阻塞

课堂练习

  1. 用计时工具为你的Agent注入瀑布图记录,分析每步的Think/Action/Observe耗时分布
  2. 观察10步Agent任务中,第1步和第10步的Think耗时差异
  3. 构造一个可能导致死循环的场景(如工具始终返回失败),验证系统的保护机制
  4. 在5并发下运行Agent任务,观察LLM服务是否扛得住放大后的调用量

11. 工作流引擎性能测试

工作流引擎(如Dify、Coze、n8n)通过可视化DAG(有向无环图)编排AI应用。与自由的ReAct不同,工作流的执行路径是预定义的,性能特征也不同。

11.1 工作流引擎的性能特征

平台架构节点执行并发能力性能特点
DifyPython + Celery串行/并行分支中等LLM节点是瓶颈
Coze云端托管串行/并行受API限流依赖字节LLM服务
n8nNode.js串行为主受内存限制HTTP节点快,LLM节点慢

11.2 DAG执行引擎的性能瓶颈

典型工作流DAG:

  [开始] → [提取意图(LLM)] → [条件分支]
                                 ├─→ [查知识库] → [Rerank] → [生成回答(LLM)] → [结束]
                                 ├─→ [调工具API] → [格式化(LLM)] → [结束]
                                 └─→ [直接回复] → [结束]

性能瓶颈层次:
  1. LLM节点(秒级)     ← 最大瓶颈
  2. HTTP/API节点(百毫秒级)
  3. 代码节点(毫秒级)
  4. 条件分支(极快但影响路径选择)
  5. 节点调度开销(每次5~20ms)
  6. 数据序列化/反序列化(每次1~10ms)

11.3 不同节点类型的性能差异

节点类型典型延迟变异系数资源消耗可优化空间
LLM节点2~15s高(±50%)GPU换更快模型、缩短Prompt
知识库检索50~500msCPU/内存索引优化、缓存
HTTP请求100~2000ms网络超时控制、连接池
代码执行1~50msCPU几乎不需要优化
条件分支< 1ms极低
变量赋值< 1ms极低

11.4 并行分支 vs 串行分支

串行分支:
  [LLM-A(3s)] → [LLM-B(4s)] → [LLM-C(2s)]
  总耗时 = 3 + 4 + 2 = 9s

并行分支:
  [LLM-A(3s)] ─┐
  [LLM-B(4s)] ─┤→ [汇总(1s)]
  [LLM-C(2s)] ─┘
  总耗时 = max(3, 4, 2) + 1 = 5s

性能提升 = 9s / 5s = 1.8x

但注意:并行分支消耗3倍LLM并发!
  串行:同一时刻只有1个LLM调用
  并行:同一时刻有3个LLM调用
  
  10并发用户 × 3并行LLM = 30个LLM并发请求

11.5 嵌套工作流的性能叠加

💡 嵌套工作流的复合延迟

主工作流(5个节点) → 其中第3个节点调用子工作流(4个节点)
                 → 子工作流第2个节点又调用孙工作流(3个节点)

总延迟 = 主流程延迟 + 子流程延迟 + 孙流程延迟
       = 5节点 + 4节点 + 3节点 = 12节点的串行延迟

如果每个LLM节点3s:12 × 3s = 36s
嵌套越深,延迟越不可控!

11.6 压测方法

工作流压测方法:
  1. API触发工作流执行
     POST /api/workflow/run
     { "workflow_id": "xxx", "inputs": {"query": "test"} }
  
  2. 记录每个节点耗时(从工作流引擎日志提取)
     Node1_start → Node1_end → Node2_start → ...
  
  3. 阶梯加压
     1 → 3 → 5 → 10 → 20 并发
     每级3~5分钟
  
  4. 观察指标:
     → 端到端延迟(从触发到返回结果)
     → 各节点延迟分布
     → LLM节点排队情况
     → 工作流引擎本身的CPU/内存

11.7 测试用例表

用例ID场景工作流结构关注指标PASS标准
WF-01简单线性流3节点串行(含1个LLM)E2E延迟< 10s
WF-02条件分支流条件判断 → 不同路径各路径延迟最长路径 < 15s
WF-03并行分支流3个LLM并行 → 汇总是否真并行≈ max(各分支)
WF-04嵌套工作流主流程调用子流程总延迟< 各层延迟之和
WF-05并发执行(10)10并发同一工作流LLM排队/引擎CPU错误率 < 1%
WF-06长工作流(10+节点)10个节点串行总延迟 / 超时< 60s

课堂练习

  1. 在你的工作流平台(Dify/Coze/n8n)中创建一个包含并行分支的工作流,验证分支是否真的并行执行
  2. 提取工作流执行日志,分析各节点的耗时分布,找出瓶颈节点
  3. 用API触发方式对工作流进行并发测试(5/10并发),观察LLM节点的排队情况
  4. 如果有嵌套工作流,测量嵌套层级对总延迟的影响

12. 多Agent协作性能测试

多Agent系统由多个独立的Agent协作完成复杂任务。每个Agent有自己的角色和能力,通过通信机制协同工作。

12.1 多Agent架构模式

模式1:主从模式(Orchestrator-Worker)

  ┌─────────────────────────────┐
  │    协调者 Agent (Orchestrator)   │
  │    负责任务分解和结果汇总         │
  └──┬──────────┬─────────┬─────┘
     ↓          ↓         ↓
 [研究Agent]  [写作Agent]  [审核Agent]
  查资料       写文章       检查质量

耗时 = 协调者分解(3s) + max(研究5s, 写作8s, 审核3s) + 汇总(3s)
     ≈ 14s(如果并行)或 19s(如果串行)

模式2:对等模式(Peer-to-Peer)

json
  [Agent-A] ←→ [Agent-B] ←→ [Agent-C]
    ↕               ↕            ↕
  各自独立工作,需要时互相请求帮助

耗时不确定:取决于互相调用的次数和深度

模式3:层级模式(Hierarchical)

json
       [总监Agent]
        ↓      ↓
  [经理Agent-A] [经理Agent-B]
    ↓     ↓      ↓      ↓
 [员工1] [员工2] [员工3] [员工4]

耗时 = 总监分配(2s) + max(经理A链路, 经理B链路) + 汇报(3s)
每层增加2~5s的调度开销

12.2 性能挑战

挑战具体表现性能影响解决思路
Agent间通信开销每次通信需要序列化/反序列化上下文每次通信增加100~500ms减少通信次数,传递摘要而非全文
上下文同步延迟协调者需要等待所有Agent完成才能汇总总延迟取决于最慢的Agent设置超时,部分结果先返回
LLM资源竞争多个Agent同时调LLMLLM排队,各Agent都变慢LLM连接池/优先级队列
结果汇总等待协调者等最慢的Agent木桶效应异步返回/超时截断
Token消耗爆炸N个Agent各自维护上下文费用 ≈ N × 单Agent费用共享上下文/摘要传递

12.3 性能测试方法

多Agent性能测试方案:

1. 单Agent基准测试
   → 每个Agent单独运行,记录各自的耗时和资源消耗
   → 作为后续对比的基准

2. 协作性能测试
   → 多Agent协作完成同一任务
   → 记录:协调开销、通信延迟、等待时间、总耗时
   → 与各Agent单独运行的总和对比

3. 并发协作测试
   → 多组Agent同时运行
   → 观察LLM资源竞争导致的性能退化
   → 找出系统能承受的并发Agent组数

4. 故障场景测试
   → 某个Agent超时或失败
   → 协调者如何处理?是否影响其他Agent?
   → 部分结果能否返回?

12.4 测试用例表

用例ID场景Agent数量关注指标PASS标准
MA-01主从模式(3 Worker)1协调+3执行总耗时 vs 串行并行时<串行的50%
MA-02层级模式(2级)1总监+2经理+4员工层级开销/总耗时总层级开销 < 10s
MA-03Agent通信延迟2个Agent互相调用通信延迟单次通信 < 500ms
MA-04LLM资源竞争5个Agent同时调LLM各Agent退化程度退化 < 3x
MA-05最慢Agent影响3个Agent, 1个特别慢总等待时间有超时截断机制
MA-06Agent故障3个Agent, 1个挂掉系统行为不整体崩溃

课堂练习

  1. 如果你的系统使用多Agent,画出Agent之间的通信关系图
  2. 测量Agent间每次通信的延迟开销
  3. 构造一个Agent特别慢的场景,验证协调者是否有超时处理
  4. 对比3个Agent并行工作 vs 串行工作的性能差异

13. Agent 异常与超时控制

Agent的异常和超时问题比普通API调用复杂得多——一个Agent可能执行了10步后才超时,前面9步的工作和Token消耗全部浪费。合理的超时控制是Agent系统的生命线。

13.1 Agent超时机制设计

超时层级作用范围典型值触发后行为
单步LLM超时单次LLM调用30~60s重试1~2次,仍超时则跳过或终止
单步工具超时单次工具调用10~30s返回错误,让Agent决定下一步
总任务超时整个Agent任务2~10min强制终止,返回中间结果
步数上限最大执行步数10~30步停止循环,总结已有结果

13.2 超时测试用例

用例1:工具超时时Agent的行为

场景:Agent需要调用数据库查询工具,但数据库响应极慢

模拟方法:
  → Mock工具接口,设置response_time=60s
  → 或在工具后端注入 sleep(60)

期望行为(按优先级):
  A. Agent检测到工具超时 → 换用备选方案(如缓存数据)
  B. Agent告知用户"数据查询较慢" → 继续其他步骤
  C. Agent等待超时 → 报错但不崩溃

最差行为:
  ❌ Agent无限等待工具响应
  ❌ Agent崩溃,前面步骤的结果全丢
  ❌ 超时的请求泄漏,占用后端资源

判定标准:
  ✅ 工具超时 < 30s, Agent有替代方案或友好提示

用例2:LLM超时时的重试策略

场景:LLM服务暂时不可用或响应极慢

测试矩阵:
  LLM超时1次 → 重试 → 成功 → 验证延迟增加是否可接受
  LLM超时2次 → 重试 → 成功 → 验证是否有退避策略
  LLM连续超时 → 重试次数上限 → 验证是否有降级方案

重试策略检查点:
  → 是否有指数退避(1s → 2s → 4s)
  → 是否有最大重试次数限制
  → 重试期间是否占用并发连接

用例3:步数上限时的优雅退出

场景:Agent陷入循环或任务过于复杂,达到步数上限

期望行为:
  → 停止继续执行
  → 总结已完成的步骤和中间结果
  → 告知用户"任务较复杂,已完成X步,以下是目前的结果..."
  → 建议用户拆分任务或提供更多信息

最差行为:
  ❌ 静默终止,不返回任何信息
  ❌ 前面所有步骤的中间数据全丢
  ❌ 返回技术错误信息(如"MaxStepsExceeded")

13.3 Agent死循环的检测方法

死循环检测策略:

策略1: 相同动作检测
  if 连续3次调用相同工具 + 相同参数:
      trigger_loop_break("检测到重复动作")

策略2: 上下文增长停滞
  if 最近5步的有效信息增量 < 阈值:
      trigger_loop_break("执行无进展")

策略3: 总Token消耗监控
  if 累计Token消耗 > 预算上限:
      trigger_budget_break("Token预算耗尽")

策略4: 时间窗口检测
  if 最近60秒内完成步骤数 > 10:
      trigger_rate_break("执行频率异常")(可能在空转)

13.4 测试用例表

用例ID场景模拟方式关注指标PASS标准
TO-01工具超时(30s)Mock工具延迟30sAgent反应/总延迟Agent在30s内切换方案
TO-02工具超时(无限)Mock工具不响应是否有超时机制有超时保护
TO-03LLM超时(单次)Mock LLM延迟60s重试行为重试后成功
TO-04LLM持续超时Mock LLM不响应降级行为有降级方案
TO-05达到步数上限给复杂任务,步数限制=5退出行为/中间结果返回中间结果
TO-06达到总超时给复杂任务,总超时=60s终止行为优雅终止+返回结果
TO-07死循环检测工具始终返回失败是否检测到循环< 5次重复后终止
TO-08Token预算耗尽复杂任务+低Token预算预算控制有预算保护

课堂练习

  1. 为你的Agent系统设计超时控制策略:确定单步超时、总超时、步数上限的具体值
  2. 模拟工具超时场景(让某个工具Mock接口返回延迟60秒),观察Agent的实际行为
  3. 构造一个死循环场景,验证系统是否有循环检测机制
  4. 达到步数上限时,检查Agent是否返回了有意义的中间结果

14. Agent 性能用例集

以下是一套完整的Agent性能测试用例集,覆盖简单、中等、复杂三种难度,每个用例包含具体的场景描述和判定标准。

14.1 简单任务用例(2~3步)

用例ID场景描述预期步骤各步骤耗时预期总耗时预期并发测试PASS标准
AG-01查天气并推荐穿搭2步:查天气→推荐Think 2s+Tool 0.5s+Think 3s< 10s10并发P95 < 15s
AG-02查订单状态2步:查订单→回答Think 2s+Tool 0.3s+Think 2s< 8s20并发P95 < 12s
AG-03简单数学计算(使用计算器工具)2步:识别→计算→回答Think 1.5s+Tool 0.1s+Think 2s< 6s20并发P95 < 10s

14.2 中等任务用例(4~6步)

用例ID场景描述预期步骤总耗时预期并发测试PASS标准
AG-04搜索商品+比价+推荐5步< 30s5并发P95 < 45s
AG-05查机票+筛选+排序+推荐4步< 25s5并发P95 < 35s
AG-06查客户信息+查订单+发邮件5步(含3次工具)< 35s5并发P95 < 50s
AG-07查知识库+汇总+格式化输出4步< 20s10并发P95 < 30s

14.3 复杂任务用例(8+步)

用例ID场景描述预期步骤总耗时预期并发测试PASS标准
AG-08多数据源分析+生成报告10步< 90s3并发P95 < 120s
AG-09代码审查(读代码+分析+建议)8步< 60s3并发P95 < 90s
AG-10多Agent协作(研究+写作+审核)12步(3个Agent)< 120s2并发P95 < 180s
AG-11端到端项目管理(查Jira+分析+汇报)8步(含MCP调用)< 60s3并发P95 < 90s
AG-12数据ETL(提取+清洗+转换+加载)10步< 90s2并发P95 < 150s

14.4 异常场景用例

用例ID场景描述期望行为PASS标准
AG-13第3步工具超时Agent切换方案或跳过总延迟 < 60s, 有替代结果
AG-14任务触发死循环在步数上限内终止< 20步终止, 返回中间结果
AG-15LLM返回格式错误Agent能自我纠正纠正后继续执行

课堂练习

  1. 从上面的用例集中选择5个最贴合你业务的用例,执行完整测试
  2. 为每个用例记录:实际步骤数、各步骤耗时、总耗时、Token消耗
  3. 用瀑布图展示至少一个复杂用例(AG-08~AG-12)的性能Profile
  4. 执行至少一个异常场景用例(AG-13~AG-15),验证系统的异常处理能力

15. 推理优化技术全景

模型推理优化是提升大模型性能的核心手段。作为测试人员,不需要亲自实施优化,但需要理解每种优化技术的原理以及如何测量优化前后的性能差异。

15.1 推理优化技术分类

推理优化技术全景图:

┌─── 模型层面 ───────────────────────────────────────────┐
│  量化(Quantization): FP16→INT8→INT4, 减少计算量和显存      │
│  蒸馏(Distillation): 大模型教小模型, 用小模型替代           │
│  剪枝(Pruning): 去掉不重要的参数, 减小模型体积             │
│  稀疏化(Sparsity): MoE架构, 每次只激活部分参数             │
└────────────────────────────────────────────────────────┘

┌─── 系统层面 ───────────────────────────────────────────┐
│  KV Cache: 缓存已计算的Key-Value, 避免重复计算             │
│  连续批处理(Continuous Batching): 动态合并请求              │
│  PagedAttention: 分页管理KV Cache, 减少显存浪费            │
│  FlashAttention: IO-aware注意力计算, 减少显存访问          │
│  Speculative Decoding: 小模型草稿+大模型验证               │
└────────────────────────────────────────────────────────┘

┌─── 硬件层面 ───────────────────────────────────────────┐
│  GPU选型: H100 vs A100 vs L40S vs RTX 4090               │
│  多卡并行: Tensor Parallel / Pipeline Parallel            │
│  CPU Offload: 部分计算卸载到CPU                            │
│  混合精度: FP16计算 + FP32累加                              │
└────────────────────────────────────────────────────────┘

┌─── 部署层面 ───────────────────────────────────────────┐
│  推理框架: vLLM / TGI / TensorRT-LLM / Ollama            │
│  容器化: Docker + NVIDIA Container Toolkit                │
│  负载均衡: 多实例 + 路由策略                                │
│  自动伸缩: 基于GPU利用率的动态扩缩容                        │
└────────────────────────────────────────────────────────┘

15.2 每种优化的一句话原理

优化技术一句话原理性能收益代价
量化用更少的位数表示模型权重速度↑ 1.5~3x, 显存↓ 2~4x质量略降
蒸馏大模型的知识压缩到小模型速度↑ 2~10x某些能力丢失
剪枝删除模型中不重要的连接速度↑ 1.2~2x需要额外微调
KV Cache缓存已算过的注意力,后续Token不重算Decode速度↑ 显著显存占用增加
连续批处理动态合并不同请求一起推理系统吞吐↑ 3~5x单请求延迟可能增
PagedAttention像操作系统管理内存一样管理KV Cache显存利用率↑ 50%实现复杂
FlashAttention重新排列注意力计算顺序减少内存访问速度↑ 10~20%, 显存↓几乎无代价
Speculative Decoding用小模型猜测多个Token再用大模型验证速度↑ 2~3x需要额外小模型

15.3 测试人员需要关心什么

✅ 测试人员的角色定位

测试人员不需要实施优化,但需要能够:

  • 测量:优化前后的TTFT、吞吐、显存、质量等全维度指标
  • 对比:制作A/B对比报告,客观展示优化效果
  • 验证:优化后质量是否可接受(尤其是量化后的质量损失)
  • 发现:优化引入的新问题(如量化后某些场景异常)

15.4 优化技术对测试的影响矩阵

优化技术对TTFT的影响对吞吐的影响对显存的影响对质量的影响测试重点
FP16→INT8降低 ~20%提升 ~30%减半轻微下降质量回归测试
FP16→INT4降低 ~40%提升 ~60%减为1/4明显下降质量回归+边界测试
连续批处理可能增加大幅提升更高效不影响高并发吞吐测试
蒸馏显著降低大幅提升大幅降低可能下降能力覆盖测试
框架替换可能变化可能变化可能变化不应变化全维度A/B测试

课堂练习

  1. 了解你项目中使用的推理优化技术有哪些(量化?连续批处理?框架?)
  2. 制作一份"优化技术清单":列出当前使用的每项优化 + 对应的性能收益
  3. 确定下一次优化计划(如从FP16切换到INT8),制定对应的性能对比测试方案

16. 量化(Quantization)与性能测试

量化是当前最常用、性价比最高的推理优化技术。通过降低模型权重的数值精度来减少计算量和显存占用。

16.1 量化基础

📖 量化是什么

FP32 (32位浮点): 1个参数占4字节   → 精度最高,速度最慢
FP16 (16位浮点): 1个参数占2字节   → 训练/推理标准精度
INT8 (8位整数):  1个参数占1字节   → 轻度量化,质量损失小
INT4 (4位整数):  1个参数占0.5字节 → 深度量化,质量有损失

以 Llama 70B 为例:
  FP32: 70B × 4 = 280GB → 需要4张A100-80GB
  FP16: 70B × 2 = 140GB → 需要2张A100-80GB
  INT8: 70B × 1 = 70GB  → 需要1张A100-80GB
  INT4: 70B × 0.5 = 35GB → 需要1张A100-40GB 或 RTX 4090

16.2 主流量化方法

方法精度需要校准数据推理速度质量保持适用框架
GPTQINT4/INT8需要(~128条)vLLM, TGI
AWQINT4需要最快很好vLLM, TGI
GGUF/GGML多种(Q2~Q8)不需要中等取决于精度llama.cpp, Ollama
bitsandbytesINT8/NF4不需要中等Transformers
SmoothQuantINT8需要很好TensorRT-LLM

16.3 量化前后的性能对比

Llama 70B 在不同量化下的性能数据(A100-80GB × 2)

量化显存占用TTFT (1并发)Token吞吐最大并发质量(MMLU)
FP16140GB800ms25 t/s~870.5%
INT8 (GPTQ)70GB550ms35 t/s~1569.8%
INT4 (AWQ)38GB400ms48 t/s~2568.2%
INT4 (GGUF Q4_K_M)40GB500ms40 t/s~2068.5%

💡 量化的性价比分析

FP16 → INT8: 显存减半,速度+40%,质量损失 < 1% → 强烈推荐
INT8 → INT4: 显存再减半,速度+35%,质量损失 ~2% → 推荐(如果质量可接受)
FP16 → INT4: 显存减为1/4,速度+90%,质量损失 ~3% → 需要评估质量

质量损失的实际影响:
  → 简单问答/分类任务:INT4质量损失几乎不可感知
  → 复杂推理/数学:INT4可能出现明显退化
  → 代码生成:INT4可能增加语法错误
  → 多语种:非主流语言退化更明显

16.4 量化性能测试方法

量化性能对比测试流程:

1. 准备测试数据集(固定,用于所有测试)
   → 100条不同类型的Prompt
   → 分类:简单问答(30) + 推理(20) + 代码(20) + 翻译(15) + 数学(15)

2. 基线测试(FP16,无量化)
   → 跑完100条,记录TTFT/吞吐/显存
   → 分别在1/5/10/20并发下测试
   → 记录质量基准(保存所有回答)

3. 量化测试(INT8 / INT4)
   → 用相同的100条Prompt
   → 相同的并发设置
   → 记录相同的指标

4. 对比分析
   → 性能维度:TTFT提升了多少%?吞吐提升了多少%?
   → 质量维度:对比同一Prompt的FP16和INT4回答
   → 显存维度:峰值显存降低了多少?
   → 成本维度:同等服务能力需要几张GPU?

16.5 测试用例表

用例ID场景对比项关注指标PASS标准
QT-01FP16 vs INT8基准对比同模型, 1并发TTFT/吞吐/显存INT8速度≥FP16
QT-02FP16 vs INT4基准对比同模型, 1并发TTFT/吞吐/显存INT4速度≥FP16×1.5
QT-03量化后并发能力FP16 vs INT8, 阶梯并发最大并发数INT8并发 ≥ FP16×1.5
QT-04量化后质量评估同100条Prompt的回答对比质量差异质量降幅 < 5%
QT-05量化边界场景数学推理/代码生成特定场景质量记录退化程度

课堂练习

  1. 如果你的模型支持量化,分别用FP16和INT8跑一组基准测试,对比TTFT和吞吐
  2. 用同一组Prompt对比FP16和INT4的回答质量,找出质量退化最明显的Prompt类型
  3. 计算量化前后的GPU显存差异,评估是否可以用更少的GPU卡达到相同性能
  4. 如果无法实际操作量化,查阅模型的量化benchmark数据,制作对比表格

17. KV Cache 与连续批处理

KV Cache和连续批处理是两项系统层面的优化技术,几乎所有现代推理框架都默认启用。理解它们对性能的影响,有助于解释压测中观察到的各种现象。

17.1 KV Cache 原理

📖 KV Cache 是什么

在Transformer架构中,生成每个新Token时需要对之前所有Token做注意力计算(计算Query、Key、Value)。KV Cache将已经计算过的Key和Value缓存起来,生成后续Token时直接复用,避免重复计算。

无KV Cache:生成第N个Token → 重新计算前N-1个Token的K和V → O(N²)
有KV Cache:生成第N个Token → 只计算第N个Token的Q → 用缓存的K,V做注意力 → O(N)

效果:Decode阶段速度提升 10~100x(长序列更明显)
代价:需要额外显存存储KV Cache

17.2 KV Cache 对性能的影响

场景无KV Cache有KV Cache提升
生成第10个Token10ms1ms10x
生成第100个Token100ms1ms100x
生成第1000个Token1000ms1ms1000x

KV Cache的显存占用

KV Cache 显存计算公式:
  KV_size = 2 × num_layers × num_heads × head_dim × seq_len × bytes_per_element

以 Llama 70B (FP16) 为例:
  每Token的KV Cache ≈ 1.2MB
  1024 Token上下文 ≈ 1.2GB
  4096 Token上下文 ≈ 4.8GB
  32K Token上下文 ≈ 38.4GB ← 接近一张A100的全部显存!

问题:长上下文场景下,KV Cache可能比模型权重还占更多显存

  10并发 × 4K上下文 = 48GB KV Cache
  → 加上模型权重 → 需要更多GPU

⚠️ KV Cache爆显存的常见场景

  • 长上下文对话(32K+):单个请求的KV Cache就可能超过30GB
  • 高并发 + 中等上下文:20并发 × 4K Token = 大量KV Cache累积
  • 多轮对话不清理:上下文持续增长,KV Cache不断膨胀

17.3 连续批处理(Continuous Batching)

传统批处理 vs 连续批处理

传统批处理(Static Batching):
  等凑齐一批请求 → 一起推理 → 所有请求完成后返回 → 处理下一批
  
  问题:短请求等长请求
  请求A(输出10 token) ─────■ 等待 ──────────────────
  请求B(输出100 token) ────■■■■■■■■■■■■■■■■■■■■
  请求C(输出30 token) ─────■■■■■■ 等待 ───────────
  
  A和C在B完成前必须等待 → GPU浪费

连续批处理(Continuous Batching):
  请求完成一个就立即释放,新请求立即加入
  
  请求A(输出10 token) ─────■ → 完成释放
  请求D(新来的) ─────────────■■■■■■■■ → 接替A的位置
  请求B(输出100 token) ────■■■■■■■■■■■■■■■■■■■■
  请求C(输出30 token) ─────■■■■■■ → 完成释放
  请求E(新来的) ────────────────────■■■■■■ → 接替C的位置

  GPU始终满载,没有浪费!

连续批处理对吞吐量的影响

批处理方式系统吞吐(10并发)单请求延迟GPU利用率
无批处理(逐个)~30 t/s最低~30%
静态批处理(batch=8)~150 t/s可能增加~70%
连续批处理~250 t/s略增加~85%
连续批处理 + PagedAttention~350 t/s略增加~90%

17.4 vLLM 的 PagedAttention

📖 PagedAttention 一句话原理

像操作系统的虚拟内存一样管理KV Cache——不需要为每个请求预分配连续的最大显存,而是按需分配小页(page),用完即释放。这样显存利用率可以提高50%以上。

17.5 测试方法

KV Cache和连续批处理的性能测试:

1. 不同batch size下的吞吐测试
   → batch_size = 1, 2, 4, 8, 16, 32
   → 记录系统吞吐和单请求延迟
   → 找到吞吐不再增长的拐点

2. 不同上下文长度下的显存测试
   → 固定并发=5
   → 上下文长度 = 512, 1024, 2048, 4096, 8192, 16384, 32768
   → 记录显存占用(nvidia-smi)
   → 找到OOM的边界

3. 连续批处理效果验证
   → 方法:发送长短混合的请求
   → 短请求(10 token) + 长请求(500 token) 混合
   → 观察短请求是否能在长请求完成前返回

课堂练习

  1. 在不同并发数下测试系统的Token吞吐,画出"并发数-系统总吞吐"曲线,找到吞吐饱和点
  2. 发送不同长度的上下文(512/2K/8K/32K Tokens),用nvidia-smi观察显存变化
  3. 发送混合长短请求,验证短请求是否能在长请求完成前返回(验证连续批处理是否生效)
  4. 计算你的模型在目标并发数下的KV Cache显存需求,判断是否有OOM风险

18. 推理框架对比测试

不同推理框架对同一模型的性能表现可能有显著差异。选择合适的推理框架是部署决策中的重要环节。

18.1 主流推理框架

框架核心技术适用场景部署难度社区活跃度
vLLMPagedAttention + 连续批处理通用生产部署中等非常活跃
TGIFlash Attention + 动态批处理HuggingFace生态简单(Docker)活跃
Ollamallama.cpp封装个人/开发调试极简非常活跃
TensorRT-LLMTensorRT + NVIDIA优化NVIDIA GPU极致性能复杂NVIDIA维护
llama.cpp纯C++, CPU/GPU混合推理CPU推理/边缘设备简单非常活跃
SGLangRadixAttention + 前缀缓存多轮对话/共享前缀中等增长中

18.2 对比测试方法

📐 推理框架对比测试的标准流程

  1. 固定变量:同一模型、同一GPU、同一测试数据集、同一并发设置
  2. 依次部署:在同一硬件上依次部署各框架
  3. 相同测试:用完全相同的压测脚本和参数
  4. 多维度记录:TTFT / 吞吐 / 显存 / 错误率 / 部署难度
  5. 多次运行:每个框架至少跑3次取平均

18.3 对比测试表模板

Qwen-14B, A100-80GB, 100条测试Prompt

指标vLLMTGIOllamaTensorRT-LLMllama.cpp
TTFT P50 (1并发)180ms220ms350ms120ms400ms
TTFT P50 (10并发)350ms400ms2000ms250ms1500ms
Token吞吐 (1并发)45 t/s42 t/s25 t/s55 t/s20 t/s
系统吞吐 (10并发)350 t/s300 t/s80 t/s450 t/s60 t/s
最大并发~30~25~5~40~3
GPU显存32GB35GB30GB28GB30GB
部署时间~10min~5min(Docker)~2min~2h(编译)~5min
支持量化AWQ/GPTQGPTQ/bitsandbytesGGUFSmoothQuant/INT8GGUF

18.4 推理框架选型建议

场景推荐框架理由
生产环境(通用)vLLMPagedAttention + 连续批处理,性能和稳定性平衡好
极致性能(NVIDIA GPU)TensorRT-LLM性能最好,但部署复杂度高
快速上手/开发调试Ollama一行命令启动,但不适合生产高并发
HuggingFace生态TGIDocker一键部署,与HF模型无缝兼容
CPU/边缘推理llama.cpp支持纯CPU推理,适合无GPU环境
多轮对话/共享System PromptSGLangRadixAttention对前缀重用优化好

课堂练习

  1. 选择2个推理框架(如vLLM和Ollama),用同一个模型部署,跑相同的压测对比性能
  2. 填写上面的对比测试表模板,用你的实际测试数据
  3. 从性能、部署难度、运维成本三个维度,为你的项目推荐最合适的推理框架
  4. 如果条件允许,测试同一模型在FP16和INT4量化下、在不同框架中的性能差异

19. 模型蒸馏与剪枝的性能影响

蒸馏和剪枝是模型层面的优化技术,通过减小模型的规模来提升推理速度和降低资源消耗。与量化不同,蒸馏和剪枝改变的是模型结构本身。

19.1 知识蒸馏(Knowledge Distillation)

📖 蒸馏是什么

用一个大的"教师模型"(Teacher)来训练一个小的"学生模型"(Student)。学生模型不仅学习正确答案,还学习教师模型的"思考方式"(输出概率分布)。目标是让小模型尽可能接近大模型的能力。

蒸馏的性能收益

对比项Teacher (70B)Student (7B)性能差异
模型大小140GB (FP16)14GB (FP16)10x 更小
GPU需求2×A100-80GB1×RTX 4090成本大幅降低
TTFT (1并发)800ms100ms8x 更快
Token吞吐25 t/s80 t/s3x 更快
最大并发~8~506x 更多
质量(MMLU)70.5%62~65%下降5~8%

蒸馏的质量代价

蒸馏后质量退化分析:

能力保持好的场景:
  ✅ 简单问答/FAQ → 保持95%以上质量
  ✅ 文本分类/情感分析 → 保持90%以上
  ✅ 信息提取/NER → 保持85%以上

能力退化明显的场景:
  ⚠️ 复杂推理/数学 → 可能退化20~40%
  ⚠️ 长文生成 → 连贯性下降
  ⚠️ 小众语言 → 退化更严重
  ⚠️ 代码生成 → 复杂代码错误率增加

测试建议:
  → 不只测平均分,要测各能力维度的分数
  → 特别关注业务核心场景的质量变化
  → 蒸馏后的模型可能在某些边界情况表现很差

19.2 模型剪枝(Pruning)

📖 剪枝是什么

剪枝是去掉模型中"不重要"的参数或结构,从而减小模型体积和计算量。类似于修剪树枝——去掉无用的枝叶,保留核心结构。

结构化剪枝 vs 非结构化剪枝

类型做什么速度提升实现难度质量影响
非结构化剪枝去掉单个不重要的权重(设为0)需要稀疏计算硬件支持简单较小
结构化剪枝去掉整个注意力头/FFN层直接减少计算量复杂(需重新训练)较大

剪枝的实际性能提升

结构化剪枝示例(去掉30%的注意力头):

原模型(32层×32头):
  → TTFT: 500ms
  → Token吞吐: 40 t/s
  → 显存: 28GB

剪枝后(32层×22头, 约减30%):
  → TTFT: 380ms (-24%)
  → Token吞吐: 52 t/s (+30%)
  → 显存: 20GB (-29%)
  → 质量: MMLU下降3~5%

注意:剪枝后通常需要额外的微调(fine-tuning)来恢复部分质量

19.3 蒸馏/剪枝的A/B性能对比方法

Teacher vs Student 全维度对比测试方案:

1. 性能对比(定量)
   ┌──────────────┬──────────┬──────────┬────────┐
   │ 指标          │ Teacher  │ Student  │ 差异    │
   ├──────────────┼──────────┼──────────┼────────┤
   │ TTFT P50     │ 800ms    │ 100ms    │ -87.5% │
   │ TTFT P95     │ 1200ms   │ 180ms    │ -85%   │
   │ 吞吐(单请求)  │ 25 t/s   │ 80 t/s   │ +220%  │
   │ 吞吐(系统,10c)│ 200 t/s  │ 600 t/s  │ +200%  │
   │ 显存占用      │ 140GB    │ 14GB     │ -90%   │
   │ 最大并发      │ 8        │ 50       │ +525%  │
   └──────────────┴──────────┴──────────┴────────┘

2. 质量对比(定量 + 定性)
   ┌──────────────┬──────────┬──────────┬────────┐
   │ 能力维度      │ Teacher  │ Student  │ 退化    │
   ├──────────────┼──────────┼──────────┼────────┤
   │ 简单问答      │ 95%      │ 92%      │ -3%    │
   │ 推理          │ 80%      │ 62%      │ -18%   │
   │ 代码          │ 85%      │ 70%      │ -15%   │
   │ 翻译          │ 90%      │ 82%      │ -8%    │
   │ 数学          │ 75%      │ 55%      │ -20%   │
   │ 综合(MMLU)    │ 70.5%    │ 63%      │ -7.5%  │
   └──────────────┴──────────┴──────────┴────────┘

3. 成本对比
   ┌──────────────┬──────────┬──────────┬────────┐
   │ 成本维度      │ Teacher  │ Student  │ 节省    │
   ├──────────────┼──────────┼──────────┼────────┤
   │ GPU成本(月)   │ ¥20,000  │ ¥3,000   │ 85%    │
   │ 电费(月)      │ ¥2,000   │ ¥400     │ 80%    │
   │ 运维复杂度    │ 高(多卡)  │ 低(单卡)  │ ↓      │
   └──────────────┴──────────┴──────────┴────────┘

课堂练习

  1. 如果你的团队在考虑用小模型替代大模型,制定一个Teacher vs Student的全维度对比方案
  2. 列出你业务中最重要的5个场景,分别用大模型和小模型测试质量差异
  3. 计算从大模型切换到小模型后的GPU成本节省
  4. 讨论:在哪些场景下质量退化是不可接受的?可以用路由策略(简单任务走小模型,复杂任务走大模型)吗?

20. 优化前后的A/B性能对比方法

无论是量化、蒸馏、框架替换还是任何其他优化,都需要一套标准的A/B对比方法来科学地评估优化效果。本章提供一个完整的方法论和模板。

20.1 A/B对比的标准流程

  1. 固定环境和数据 → 2. 跑基线(A) → 3. 实施优化 → 4. 跑优化后(B) → 5. 多维度对比

步骤1:固定测试环境和数据

💡 控制变量的重要性

每次只改一个变量!如果同时换了框架+开了量化+升级了CUDA,就无法知道性能提升来自哪个优化。

必须固定的变量:
  ✅ GPU型号和数量
  ✅ CUDA版本
  ✅ 操作系统和驱动
  ✅ 测试数据集(100条固定Prompt)
  ✅ 并发数和持续时间
  ✅ max_tokens和temperature
  ✅ 测试时间段(避免不同时段的负载干扰)

每次改变的变量(只改一个):
  🔄 量化精度(FP16 → INT8)
  🔄 推理框架(vLLM → TGI)
  🔄 模型版本(14B → 7B蒸馏)
  🔄 batch size 参数

步骤2~4:执行测试

执行注意事项:
  → 每个配置至少跑3次取平均(降低随机波动影响)
  → 每次测试前重启服务(清除缓存状态)
  → 预热:正式测试前先跑10个请求预热GPU
  → 记录完整的系统指标(GPU/CPU/内存/网络)
  → 保存原始数据(不只是汇总统计)

20.2 统计显著性

📐 跑3次取平均 vs 跑1次

跑1次的问题:
  → 可能刚好遇到GPU热节流
  → 可能后台有其他进程抢资源
  → 可能网络刚好不稳定
  → 结论不可靠

跑3次取平均:
  结果1: TTFT P50 = 320ms
  结果2: TTFT P50 = 345ms
  结果3: TTFT P50 = 330ms
  平均: 332ms, 标准差: 12.6ms
  变异系数: 3.8% → 结果稳定可信

如果3次结果差异 > 20% → 环境不稳定,需要排查

理想情况:跑5次取中位数,更加稳健

20.3 A/B对比报告模板

TIP

═══════════════════════════════════════════════════════
  A/B 性能对比报告
═══════════════════════════════════════════════════════

1. 对比目的
   验证 vLLM FP16 → vLLM INT8 量化后的性能变化

2. 测试环境(固定)
   GPU: NVIDIA A100-80GB × 1
   模型: Qwen2-14B-Instruct
   CUDA: 12.2  |  Driver: 535.104
   测试数据: 100条固定Prompt(30简单+30中等+40复杂)
   并发: 分别在 1/5/10/20 下测试
   max_tokens: 200  |  temperature: 0.7
   每个配置运行3次取平均

3. 变量
   A组: vLLM + FP16(无量化)
   B组: vLLM + INT8(AWQ量化)

4. 性能对比结果

  4.1 TTFT (ms)
  ┌──────────┬──────┬──────┬──────────┐
  │ 并发      │ FP16 │ INT8 │ 提升      │
  ├──────────┼──────┼──────┼──────────┤
  │ 1        │ 250  │ 180  │ -28.0%   │
  │ 5        │ 380  │ 280  │ -26.3%   │
  │ 10       │ 650  │ 450  │ -30.8%   │
  │ 20       │ 1500 │ 900  │ -40.0%   │
  └──────────┴──────┴──────┴──────────┘

  4.2 Token 吞吐 (tokens/s)
  ┌──────────┬──────┬──────┬──────────┐
  │ 并发      │ FP16 │ INT8 │ 提升      │
  ├──────────┼──────┼──────┼──────────┤
  │ 单请求    │ 40   │ 55   │ +37.5%   │
  │ 系统(10c) │ 320  │ 450  │ +40.6%   │
  │ 系统(20c) │ 500  │ 720  │ +44.0%   │
  └──────────┴──────┴──────┴──────────┘

  4.3 GPU 资源
  ┌──────────────┬──────┬──────┬──────────┐
  │ 指标          │ FP16 │ INT8 │ 变化      │
  ├──────────────┼──────┼──────┼──────────┤
  │ 显存占用      │ 30GB │ 16GB │ -46.7%   │
  │ GPU利用率(10c)│ 85%  │ 70%  │ -15pp    │
  │ 温度(10c)    │ 72°C │ 65°C │ -7°C     │
  │ 最大并发      │ 25   │ 40   │ +60.0%   │
  └──────────────┴──────┴──────┴──────────┘

  4.4 质量对比(100条Prompt)
  ┌──────────────┬──────┬──────┬──────────┐
  │ 类型          │ FP16 │ INT8 │ 差异      │
  ├──────────────┼──────┼──────┼──────────┤
  │ 简单问答(30)  │ 29/30│ 28/30│ -3.3%    │
  │ 中等任务(30)  │ 27/30│ 26/30│ -3.7%    │
  │ 复杂推理(40)  │ 34/40│ 31/40│ -8.8%    │
  │ 总计          │ 90%  │ 85%  │ -5.0%    │
  └──────────────┴──────┴──────┴──────────┘

5. 结论
   ✅ INT8量化后性能提升显著:
      → TTFT降低28~40%
      → Token吞吐提升37~44%
      → 显存降低47%
      → 最大并发提升60%
   
   ⚠️ 质量代价:
      → 简单任务几乎无影响(-3.3%)
      → 复杂推理有一定退化(-8.8%)
      → 综合质量下降5%
   
   📌 建议:
      → 推荐在生产环境启用INT8量化
      → 对复杂推理场景保留FP16回退选项
      → 节省的GPU资源可用于增加并发或部署备份

20.4 三方对比示例:vLLM FP16 vs vLLM INT8 vs TGI FP16

指标vLLM FP16vLLM INT8TGI FP16最优
TTFT P50 (10并发)650ms450ms700msvLLM INT8
系统吞吐 (10并发)320 t/s450 t/s280 t/svLLM INT8
显存占用30GB16GB33GBvLLM INT8
最大并发254020vLLM INT8
质量90%85%90%vLLM FP16 / TGI
部署难度中等中等简单(Docker)TGI

20.5 常见对比测试的坑

⚠️ 常见错误,导致对比结论不可靠

  • 不预热:第一次请求触发模型加载,TTFT异常高,拉高平均值
  • 同时改多个变量:框架+量化一起换,不知道性能提升归因于哪个
  • 只跑1次:单次运行的随机波动可能导致错误结论
  • 忽略质量维度:只看速度不看质量,可能推荐了一个"快但质量差"的方案
  • 不同时段测试:A组白天测,B组晚上测,GPU温度和系统负载不同
  • 测试数据不固定:A组用简单Prompt,B组用复杂Prompt

课堂练习

  1. 选择你最想优化的一个维度(量化/框架/模型大小),按照本章的标准流程做一次A/B对比
  2. 确保每个配置跑3次取平均,记录标准差
  3. 使用本章的报告模板编写一份完整的A/B对比报告
  4. 在报告中明确标注质量维度的变化——性能提升不能以牺牲业务核心质量为代价
  5. 将报告分享给团队,讨论优化方案是否可以落地

补充参考答案要点

  • 前沿篇练习的答案要特别关注量化、蒸馏、MoE、长上下文和 speculative decoding 对质量与性能的双向影响。
  • 前沿优化不能只报吞吐提升,还必须说明是否带来边界退化、格式退化或复杂推理退化。
  • 真正合格的答案,应包含实验对照、指标变化和适用场景限制三部分。