• Self-Attention原理
• 复杂度分析
• KV Cache动机
• 内存占用计算
• IO感知原理
• 分块计算(Tiling)
• Online Softmax
• 实现源码分析
• vLLM核心原理
• 内存分页管理
• Copy-on-Write
• 连续批处理
• Continuous Batching
• 投机解码
• 多卡推理
• 性能对比测试
// KV Cache内存计算公式 // 对于单个序列: KV_Cache_Size = 2 × num_layers × num_heads × seq_len × head_dim × dtype_size // 示例:Llama-2-70B // num_layers=80, num_heads=64, head_dim=128, seq_len=4096, FP16 KV_Cache = 2 × 80 × 64 × 4096 × 128 × 2 bytes = 2 × 80 × 64 × 4096 × 128 × 2 = 10.7 GB (单序列!) // 这就是为什么大模型推理需要巨大显存
// Standard Attention // 1. 计算 S = Q × K^T (N×N矩阵,O(N²)内存) // 2. 计算 P = softmax(S) (N×N矩阵) // 3. 计算 O = P × V (输出) // 总内存: O(N²) + O(N×d) = O(N²) // FlashAttention // 1. 分块加载Q,K,V到SRAM // 2. 在SRAM中计算部分注意力 // 3. Online Softmax更新统计量 // 4. 逐步累加输出 // 总内存: O(N) - 只需要存储输出和统计量
# FlashAttention Python接口 from flash_attn import flash_attn_func # q, k, v: [batch, seqlen, nheads, headdim] # 不同head_dim需要不同版本的FlashAttention output = flash_attn_func(q, k, v, causal=True) # FlashAttention-2 (更快) from flash_attn import flash_attn_func output = flash_attn_func(q, k, v, causal=True, window_size=(-1, -1))
# PagedAttention内存管理 # 传统方法:每个序列预分配max_seq_len内存 # PagedAttention:按需分配Block # 示例: # 序列1: 100 tokens → 7个Block (每个Block 16 tokens) # 序列2: 50 tokens → 4个Block # 序列3: 200 tokens → 13个Block # 总共: 24个Block (而不是350个Block预分配)
# vLLM安装和使用 pip install vllm # 基本使用 from vllm import LLM, SamplingParams # 初始化模型 llm = LLM( model="meta-llama/Llama-2-7b-hf", tensor_parallel_size=2, # 2卡并行 max_model_len=4096, gpu_memory_utilization=0.9 ) # 批量生成 prompts = ["Hello, how are you?", "What is AI?"] sampling_params = SamplingParams(temperature=0.7, max_tokens=100) outputs = llm.generate(prompts, sampling_params)