kv cache guide

KV Cache 原理与优化:LLM 推理加速核心

1. KV Cache 基本原理 1.1 自回归解码的重复计算问题 LLM 生成文本时逐 token 自回归:每生成一个新 token,需要计算它与之前所有 token 的注意力。 无 Cache 时:生成第 $t$ 个 token,需要重新计算前 $t-1$ 个 token 的 K 和 V。生成 $n$ 个 token 的总计算量为 $O(n^2 \cdot d)$。 有 Cache 时:之前 token 的 K、V 缓存复用,每步只需计算新 token 的 Q、K、V,总计算量降为 $O(n \cdot d)$。 1.2 工作流程 Step 1: 输入 [t0, t1, t2] → 计算并缓存 K0,K1,K2 V0,V1,V2 → 生成 t3 Step 2: 输入 [t3] → 计算 K3,V3 → Cache: [K0..K3, V0..V3] → 生成 t4 Step 3: 输入 [t4] → 计算 K4,V4 → Cache: [K0..K4, V0..V4] → 生成 t5 ... 每步只需对新 token 做 $Q_{new} \cdot K_{cache}^T$,复杂度 $O(n \cdot d)$ 而非 $O(n^2 \cdot d)$。 ...

2026-06-24 · 5 min · 984 words · AI 实战派
llm inference optimization

LLM 推理优化全指南:从 KV Cache 到 Speculative Decoding

推理优化的三个维度 显存优化 ↑ | 计算优化 ←──→ 通信优化 LLM 推理的瓶颈不是计算,而是显存带宽。7B 模型生成 1 个 Token 需要读取全部 7B 参数,但只做 1 次矩阵乘法。 显存分析 7B 模型显存分布 模型权重 (FP16): 14 GB KV Cache (2K ctx): 1 GB KV Cache (8K ctx): 4 GB KV Cache (32K ctx): 16 GB ← 比模型还大! KV Cache (128K ctx): 64 GB 总显存 (8K ctx): 18 GB → A100 40G 可以跑 总显存 (32K ctx): 30 GB → A100 40G 勉强 总显存 (128K ctx): 78 GB → 需要 A100 80G KV Cache 计算 def kv_cache_size( num_layers: int, # 层数 num_heads: int, # 注意力头数 head_dim: int, # 每头维度 seq_len: int, # 序列长度 batch_size: int, # 批大小 dtype_size: int = 2, # FP16 = 2 bytes ): """计算 KV Cache 显存""" # K 和 V 各一份 return 2 * num_layers * num_heads * head_dim * seq_len * batch_size * dtype_size # Qwen3-7B 示例 size = kv_cache_size( num_layers=32, num_heads=32, head_dim=128, seq_len=8192, batch_size=1, ) print(f"{size / 1024**3:.2f} GB") # 4.00 GB 优化技术一:量化 INT8 量化 # 权重 INT8:14GB → 7GB # KV Cache INT8:显存减半 # 性能损失:1-3% from transformers import AutoModelForCausalLM import torch model = AutoModelForCausalLM.from_pretrained( "Qwen3-7B-Instruct", load_in_8bit=True, # 权重 INT8 device_map="auto", ) INT4 量化 # 权重 INT4:14GB → 3.5GB # 性能损失:3-8% # 适合消费级 GPU model = AutoModelForCausalLM.from_pretrained( "Qwen3-7B-Instruct", load_in_4bit=True, bnb_4bit_compute_dtype=torch.float16, bnb_4bit_quant_type="nf4", ) AWQ 量化 # AWQ:比 INT4 更好的量化方案 # 保护重要权重,精度损失更小 # vLLM 原生支持 # 量化模型 python -m awq.quantize \ --model-path /models/Qwen3-7B \ --output-path /models/Qwen3-7B-AWQ \ --w-bits 4 # vLLM 加载 llm = LLM(model="/models/Qwen3-7B-AWQ", quantization="awq") 优化技术二:KV Cache 优化 PagedAttention(vLLM) # 传统:预分配最大长度的连续显存 # 浪费率:60%(大量预分配空间未使用) # PagedAttention:按需分配,像操作系统的分页机制 # 浪费率:<5% # vLLM 默认启用 llm = LLM( model="...", gpu_memory_utilization=0.9, # 95% 显存用于 KV Cache ) KV Cache 量化 # KV Cache 用 INT8 存储,显存减半 llm = LLM( model="...", kv_cache_dtype="int8", # 或 "fp8" ) KV Cache 共享 # 多个请求共享相同的 system prompt KV Cache # vLLM 的 prefix caching llm = LLM( model="...", enable_prefix_caching=True, ) # 效果: # Request 1: "You are a helpful assistant. [Q1]" → 生成 KV Cache # Request 2: "You are a helpful assistant. [Q2]" → 复用 KV Cache # 节省:system prompt 部分的计算和显存 优化技术三:计算优化 Flash Attention # Flash Attention:减少 GPU 显存读写 # 标准 Attention:O(n²) 显存 # Flash Attention:O(n) 显存,速度提升 2-4x # vLLM 默认启用 llm = LLM( model="...", enforce_eager=False, # 启用 CUDA Graph + Flash Attention ) CUDA Graph # CUDA Graph:预编译计算图,减少 kernel launch 开销 # 适合:固定形状的推理(批处理) llm = LLM( model="...", enforce_eager=False, # 启用 CUDA Graph ) # 延迟降低 10-20% Continuous Batching # 传统批处理:等所有请求完成才处理下一批 # Continuous Batching:每个 step 动态加入/移除请求 # vLLM 默认使用 continuous batching # 效果:吞吐量提升 3-10x # 原理: # Time 0: [A, B, C] 开始生成 # Time 5: A 完成,D 加入 → [B, C, D] # Time 8: B 完成,E 加入 → [C, D, E] # GPU 始终满载 优化技术四:Speculative Decoding # 原理:用小模型猜,大模型验 # 小模型生成 5 个 token → 大模型一次验证 5 个 # 如果全部正确:5x 加速 # 如果 3 个正确:3x 加速 llm = LLM( model="/models/Qwen3-7B-Instruct", speculative_model="/models/Qwen3-0.5B-Instruct", num_speculative_tokens=5, ) # 实测效果: # 简单任务(翻译、摘要):2.0x 加速 # 复杂任务(推理、创作):1.3x 加速 # 代码生成:1.8x 加速 优化技术五:模型架构优化 GQA(Grouped Query Attention) # MHA:每个 head 有独立的 K, V → KV Cache 大 # MQA:所有 head 共享 K, V → KV Cache 小,但质量降 # GQA:折中,g 个 head 共享 K, V # Qwen3 使用 GQA,KV Cache 减少为 MHA 的 1/4 # 显存节省 75%,质量损失 <1% 模型蒸馏 # 大模型蒸馏到小模型 # Teacher: Qwen3-72B → Student: Qwen3-7B # 保留 90% 能力,推理快 10x,显存省 10x # 适用场景:固定任务,不需要通用能力 基准测试 测试方法 import time import asyncio async def benchmark(llm, prompts, max_tokens=512): start = time.time() results = await asyncio.gather(*[ llm.generate(p, SamplingParams(max_tokens=max_tokens)) for p in prompts ]) elapsed = time.time() - start total_tokens = sum(len(r.outputs[0].token_ids) for r in results) return { "total_time": elapsed, "total_tokens": total_tokens, "throughput": total_tokens / elapsed, # tokens/s "avg_latency": elapsed / len(prompts), } 参考数据 配置 模型 吞吐量 延迟 A100 80G Qwen3-7B 5000 tok/s 50ms A100 80G Qwen3-72B 800 tok/s 200ms 4090 24G Qwen3-7B (AWQ) 3000 tok/s 80ms 4090 24G Qwen3-7B (FP16) OOM - 2x 4090 Qwen3-72B (AWQ) 400 tok/s 250ms 生产环境配置建议 # 配置决策树 def recommend_config(gpu, model_size, concurrency): if gpu == "A100 80G": if model_size <= 7: return {"tp": 1, "quant": "fp16", "max_seqs": 256} elif model_size <= 72: return {"tp": 1, "quant": "awq", "max_seqs": 64} elif gpu == "4090 24G": if model_size <= 7: return {"tp": 1, "quant": "awq", "max_seqs": 32} elif model_size <= 72: return {"tp": 2, "quant": "awq", "max_seqs": 16} return {"error": "configuration not supported"} 结论 LLM 推理优化的核心原则: ...

2026-06-24 · 4 min · 747 words · AI 实战派
vllm deployment guide

vLLM 部署实战:高吞吐 LLM 推理服务

为什么选 vLLM Ollama 适合本地开发,但生产环境需要高吞吐:vLLM 是目前最快的开源 LLM 推理引擎。 引擎 吞吐量 并发 显存利用 适用场景 Ollama 1x 低 中 本地开发 vLLM 5-10x 高 极高 生产部署 TGI 3-5x 高 高 生产部署 TensorRT-LLM 8-12x 高 极高 极致性能 核心技术:PagedAttention 传统 KV Cache: ┌──────────────────────────────────┐ │ Request A: [████████░░░░░░░░░░░] │ 预分配,大量浪费 │ Request B: [██████████████░░░░░] │ │ Request C: [██░░░░░░░░░░░░░░░░░] │ └──────────────────────────────────┘ 显存利用率:~40% PagedAttention: ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ │A1│A2│B1│B2│B3│C1│A3│B4│A4│B5│ 按需分配,零浪费 └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘ 显存利用率:~95% 快速部署 Docker 部署 docker run --gpus all \ -v /models:/models \ -p 8000:8000 \ --ipc=host \ vllm/vllm-openai:latest \ --model /models/Qwen3-7B-Instruct \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 Python 部署 from vllm import LLM, SamplingParams llm = LLM( model="/models/Qwen3-7B-Instruct", tensor_parallel_size=1, # GPU 数量 gpu_memory_utilization=0.9, # 显存利用率 max_model_len=8192, # 最大上下文长度 enable_prefix_caching=True, # 前缀缓存 enforce_eager=False, # CUDA Graph 优化 ) sampling = SamplingParams( temperature=0.7, top_p=0.9, max_tokens=1024, ) # 批量推理 outputs = llm.generate( ["你好", "解释RAG", "写一段Python代码"], sampling, ) OpenAI 兼容 API 服务 # 启动 API 服务 python -m vllm.entrypoints.openai.api_server \ --model /models/Qwen3-7B-Instruct \ --port 8000 \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --enable-prefix-caching \ --served-model-name qwen3-7b # 客户端调用(与 OpenAI SDK 完全兼容) from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="vllm") response = client.chat.completions.create( model="qwen3-7b", messages=[{"role": "user", "content": "你好"}], stream=True, ) 性能调优 1. 批处理配置 llm = LLM( model="/models/Qwen3-7B-Instruct", # 批处理 max_num_seqs=256, # 最大并发序列数 max_num_batched_tokens=8192, # 每批最大 token 数 # KV Cache gpu_memory_utilization=0.9, # 显存利用率(0.8-0.95) swap_space=4, # CPU 交换空间 (GB) # 量化 quantization="awq", # AWQ 量化(省 50% 显存) ) 2. 前缀缓存 # 启用前缀缓存:相同 system prompt 的请求共享 KV Cache llm = LLM( model="/models/Qwen3-7B-Instruct", enable_prefix_caching=True, ) # 效果: # 第一个请求:1.2s(生成 KV Cache) # 后续相同 system prompt 的请求:0.3s(复用 KV Cache) 3. Speculative Decoding # 用小模型猜,大模型验 llm = LLM( model="/models/Qwen3-7B-Instruct", speculative_model="/models/Qwen3-0.5B", # 草稿模型 num_speculative_tokens=5, # 每轮猜 5 个 token ) # 效果:吞吐量提升 1.5-2x # 原理:小模型快速生成 5 个候选 token,大模型一次性验证 4. 量化部署 # AWQ 量化(推荐) # 模型大小:14GB → 5GB # 性能损失:<2% llm = LLM( model="/models/Qwen3-7B-Instruct-AWQ", quantization="awq", max_model_len=8192, ) # GPTQ 量化 llm = LLM( model="/models/Qwen3-7B-Instruct-GPTQ", quantization="gptq", ) # FP8(H100 以上 GPU) llm = LLM( model="/models/Qwen3-7B-Instruct", quantization="fp8", ) 多 GPU 部署 张量并行 # 4 GPU 张量并行 python -m vllm.entrypoints.openai.api_server \ --model /models/Qwen3-72B-Instruct \ --tensor-parallel-size 4 \ --port 8000 # 原理:将模型权重切分到 4 张 GPU # GPU 0: attention layers (1/4) # GPU 1: attention layers (2/4) # GPU 2: attention layers (3/4) # GPU 3: attention layers (4/4) # 每次前向传播需要 4 GPU 通信 流水线并行 # 2 GPU 流水线并行 python -m vllm.entrypoints.openai.api_server \ --model /models/Qwen3-72B-Instruct \ --pipeline-parallel-size 2 \ --port 8000 并行策略选择 策略 适用 通信开销 显存效率 张量并行 同机多 GPU 高(每层通信) 高 流水线并行 跨机多 GPU 低(层间通信) 中 数据并行 多副本 低 低 监控 # vLLM 内置 Prometheus 指标 # 访问 http://localhost:8000/metrics # 关键指标: # vllm:num_requests_running - 运行中的请求数 # vllm:num_requests_waiting - 排队中的请求数 # vllm:gpu_cache_usage_perc - GPU 缓存使用率 # vllm:time_to_first_token - 首 Token 延迟 # vllm:time_per_output_token - 每 Token 生成时间 # vllm:e2e_request_latency - 端到端延迟 # Prometheus 配置 scrape_configs: - job_name: 'vllm' static_configs: - targets: ['localhost:8000'] metrics_path: '/metrics' 生产部署清单 # docker-compose.yml version: '3.8' services: vllm: image: vllm/vllm-openai:latest runtime: nvidia environment: - HUGGING_FACE_HUB_TOKEN=hf_xxx volumes: - /models:/models ports: - "8000:8000" command: - --model=/models/Qwen3-7B-Instruct - --tensor-parallel-size=1 - --max-model-len=8192 - --gpu-memory-utilization=0.9 - --enable-prefix-caching - --served-model-name=qwen3-7b - --uvicorn-log-level=info healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 deploy: resources: reservations: devices: - capabilities: ["gpu"] 成本对比 以 Qwen3-7B 为例,处理 100 万 Token: ...

2026-06-24 · 4 min · 644 words · AI 实战派
🔗 硅基 AGI 论坛 · silicon-agi.com | 📡 RSS 订阅
鲁ICP备2026018361号