NOTE
推理优化(Inference Optimization)
从延迟、吞吐量、显存和成本等指标入手,梳理模型、推理引擎与服务层的优化方法。
推理优化(Inference Optimization)
1. 是什么
- 在满足模型质量要求的前提下,通过优化模型、硬件和推理服务,提高推理速度与资源利用效率,降低推理成本
- 推理(Inference)
- 是什么
- 使用训练完成的模型,根据输入计算输出
- 与训练的区别
- 训练
- 前向传播
- 损失计算
- 反向传播
- 参数更新
- 推理
- 通常只执行前向传播
- 不更新模型参数
- 训练
- 是什么
- 优化
- 优化层次
- 模型层(Model)
- 优化模型规模、架构及计算过程
- 硬件层(Hardware)
- 优化计算能力、内存及硬件效率
- 服务层(Serving)
- 优化请求调度、资源分配和并发处理
- 模型层(Model)
- 优化层次
2. 为什么需要推理优化
- 存在性能问题
- 基础模型推理需要大量计算和内存资源 / ,实际部署面临成本、延迟和吞吐量问题,因此需要推理优化
- 模型参数量大
- 需要大量内存存储权重
- 计算量大
- 推理过程中需要执行大量矩阵运算
- 多用户并发
- 需要额外的计算和内存资源
- 输出Token数量多
- 增加推理延迟
- 增加推理成本
- 模型参数量大
- 基础模型推理需要大量计算和内存资源 / ,实际部署面临成本、延迟和吞吐量问题,因此需要推理优化
- 为什么会有性能问题
- 2.2 自回归生成效率有限
- 是什么
- 自回归语言模型通常逐个生成Token
- 为什么效率低
- 后一个Token依赖之前已经生成的Token
- 无法像Prefill阶段一样并行计算全部输出Token
- 示例
- 生成100个Token
- 每个Token需要100ms
- 解码过程大约需要10秒
- 是什么
- 2.2 自回归生成效率有限
4. 如何优化
- 4.1 确定性能目标
- 核心目标
- 降低延迟
- 提高吞吐量
- 降低推理成本
- 满足模型质量要求
- 目标之间的权衡
- 延迟与资源
- 降低单个请求的延迟可能需要分配更多计算资源
- 吞吐量与延迟
- 提高Batch Size通常有利于提高吞吐量
- 但可能增加请求等待时间
- 成本与性能
- 增加硬件资源可能提高吞吐量或降低延迟
- 但会增加部署和运行成本
- 推理效率与模型质量
- 降低数值精度可能减少计算和内存开销
- 但可能影响模型输出质量
- 延迟与资源
- 确定服务质量要求
- 明确延迟要求
- 明确吞吐量要求
- 明确成本预算
- 明确模型质量要求
- 明确并发量与输入输出长度
- 核心目标
- 4.2 建立性能衡量指标
- 延迟(Latency)
- TTFT(Time To First Token)
- 是什么
- 从提交请求到生成第一个输出Token的时间
- 主要关联
- 请求排队
- 调度与输入处理
- Prefill
- 输入长度
- 是什么
- TPOT(Time Per Output Token)
- 是什么
- 第一个输出Token之后,后续输出Token的平均生成时间
- 主要关联
- Decode
- 内存带宽
- 批处理与资源调度
- 是什么
- TBT / ITL
- 是什么
- 相邻输出Token之间的时间间隔
- 注意
- 不同系统的统计口径可能不同
- 是什么
- 总响应时间
- 近似公式
- TTFT + TPOT ×(输出Token数 - 1)
- 注意
- 该公式假设TPOT表示第一个Token之后的平均Token间隔
- 实际测量还可能受到排队、网络传输等因素影响
- 近似公式
- 延迟分布
- p50
- p90
- p95
- p99
- 为什么需要
- 平均值可能掩盖长尾请求
- 高分位延迟反映较慢请求的体验
- TTFT(Time To First Token)
- 吞吐量(Throughput)
- 是什么
- 单位时间内系统处理的工作量
- 请求吞吐量
- RPS
- 每秒请求数
- RPM
- 每分钟请求数
- RPS
- Token吞吐量
- 输入Token吞吐量
- 输出Token吞吐量
- 总Token吞吐量
- 注意
- 请求吞吐量与Token吞吐量衡量的对象不同
- 比较不同系统时需要统一统计口径
- 是什么
- 有效吞吐量(Goodput)
- 是什么
- 单位时间内满足指定服务质量要求的有效处理量
- 示例
- 系统每秒完成10个请求
- 只有3个请求满足延迟要求
- 若统计单位是满足要求的请求数,则Goodput为3 requests/s
- 为什么需要
- 单纯提高吞吐量可能增加超时或延迟超标的请求
- 是什么
- 资源利用率与执行效率
- GPU Utilization
- 是什么
- GPU处于活跃状态的时间比例
- 注意
- 不等于实际计算效率
- 是什么
- MFU(Model FLOP/s Utilization)
- 是什么
- 实际模型计算量相对于理论计算能力的利用程度
- 用途
- 辅助判断计算执行效率
- 是什么
- MBU(Model Bandwidth Utilization)
- 是什么
- 实际内存带宽与理论最大带宽之比
- 公式
- MBU = 实际使用带宽 / 理论最大带宽
- 用途
- 辅助判断内存带宽利用情况
- 是什么
- 分析注意事项
- 高利用率不代表业务性能一定好
- 需要结合延迟、吞吐量和资源瓶颈判断
- 计算受限时重点关注计算效率
- 内存带宽受限时重点关注带宽利用情况
- GPU Utilization
- 成本(Cost)
- Cost per Request
- Cost per Token
- Cost per Million Tokens
- 硬件租用成本
- 能源与运行成本
- 注意
- 需要明确成本统计周期与分摊方式
- 需要结合有效吞吐量分析实际服务成本
- 模型质量(Model Quality)
- 为什么需要
- 量化和剪枝可能降低模型质量
- 蒸馏可能无法保留教师模型的全部能力
- 部分优化可能改变模型行为
- 如何评估
- 复用第4章评估方法论
- 使用相同测试集
- 比较优化前后的结果
- 检查任务成功率
- 检查正确性与指令遵循
- 为什么需要
- 延迟(Latency)
- 4.3 识别性能瓶颈
- 分析原则
- 先观察性能指标是否达到目标
- 再定位时间消耗与资源开销
- 通过测量和实验确定主要瓶颈
- 不要仅凭技术名称或表面现象判断瓶颈
- 计算受限(Compute-bound)
- 是什么
- 执行时间主要受计算能力限制
- 计算单元是主要瓶颈
- 典型场景
- LLM Prefill阶段通常可能受计算能力限制
- 某些图像生成模型的推理
- 分析方向
- 检查计算量
- 检查计算执行效率
- 检查MFU等指标
- 可能的优化方向
- Kernel Optimization
- Compiler Optimization
- 量化
- 硬件计算能力优化
- 注意
- Prefill并非在所有工作负载下都一定是计算受限
- 是什么
- 内存带宽受限(Memory Bandwidth-bound)
- 是什么
- 执行时间主要受数据传输速度限制
- 计算单元需要等待模型权重或其他数据从内存加载
- 典型场景
- LLM Decode阶段通常可能受内存带宽限制
- 尤其是较低Batch Size的自回归解码
- 分析方向
- 检查权重读取开销
- 检查KV Cache读取开销
- 检查内存带宽利用情况
- 可能的优化方向
- Quantization
- 优化内存访问
- 提高Batch Size以改善资源利用率
- Kernel与算子执行优化
- 注意
- 提高Batch Size可能增加延迟和KV Cache占用
- 是什么
- 内存容量限制(Memory Capacity)
- 是什么
- 模型权重、KV Cache及其他运行数据无法在可用内存中容纳
- 典型问题
- OOM
- 模型无法完整加载
- 长上下文和高并发请求占用大量KV Cache
- 分析方向
- 分析模型权重占用
- 分析KV Cache占用
- 分析运行时临时数据占用
- 分析并发请求带来的内存增长
- 可能的优化方向
- Quantization
- Distillation
- Pruning
- KV Cache Quantization
- KV Cache Compression
- PagedAttention
- Model Parallelism
- 扩展硬件内存容量
- 注意
- PagedAttention主要改善KV Cache的管理与分配效率
- 它本身不会自动减少每个Token所需的KV数据量
- 是什么
- 排队与调度瓶颈
- 是什么
- 请求等待调度或等待执行资源
- 可能原因
- 请求到达速率超过系统处理能力
- Batch等待时间过长
- Prefill与Decode互相争用资源
- 调度策略不合理
- 可能的优化方向
- Dynamic Batching
- Continuous Batching
- Prefill/Decode Disaggregation
- Replica Parallelism
- 是什么
- 计算与通信瓶颈
- 是什么
- 跨设备通信或同步开销影响执行效率
- 可能原因
- Tensor Parallelism的设备间通信
- Pipeline Parallelism的阶段间传输
- 分布式系统中的数据传输与同步
- 可能的优化方向
- 调整并行策略
- 优化通信与计算重叠
- 评估设备互联带宽
- 是什么
- 分析原则
- 4.4 选择优化技术
- 模型权重占用过大
- 先判断
- 模型是否无法加载
- 权重是否占用过多显存
- 权重读取是否造成内存带宽瓶颈
- 候选技术
- Quantization
- 降低权重数值精度
- 减少权重存储开销
- 可能降低内存带宽需求
- 需要评估模型质量
- Distillation
- 训练能力较小的学生模型
- 部署更小的学生模型可以降低推理开销
- 需要额外训练
- 可能无法保留教师模型的全部能力
- Pruning
- 移除部分参数或结构
- 可能降低模型规模与计算开销
- 需要评估稀疏结构是否受到硬件高效支持
- Quantization
- 注意
- 蒸馏不是直接压缩现有模型权重的操作
- 非结构化剪枝产生稀疏权重不代表推理必然加速
- 先判断
- Decode延迟高
- 先判断
- TPOT是否超过目标
- 主要瓶颈是内存带宽还是计算
- 是否存在排队或调度开销
- 是否受到KV Cache读取开销影响
- 候选技术
- Speculative Decoding
- 使用草稿模型生成候选Token
- 由目标模型验证候选序列
- 减少目标模型的顺序解码次数
- 收益取决于草稿开销与候选Token接受情况
- Parallel Decoding
- 尝试并行预测多个未来Token
- 通过验证或筛选确定可接受的输出
- 代表技术包括Lookahead Decoding和Medusa
- 不同方案可能需要额外训练或修改模型
- Attention Optimization
- 在注意力计算或KV Cache访问构成瓶颈时考虑
- 需要根据实际瓶颈选择具体技术
- Speculative Decoding
- 注意
- 推测解码与并行解码并非适用于所有负载
- 应同时评估TPOT、吞吐量、成本与输出质量
- 先判断
- 长上下文导致KV Cache占用过大
- 先判断
- KV Cache是否是主要内存占用来源
- 问题是内存容量不足还是内存访问开销过大
- 是否需要保留完整历史上下文
- 候选技术
- KV Cache Quantization
- 降低缓存数值精度
- 减少缓存占用
- 需要评估精度损失
- KV Cache Compression
- 压缩缓存内容
- 减少缓存存储需求
- Selective KV Cache
- 选择性保留缓存信息
- 需要评估被丢弃信息对模型质量的影响
- PagedAttention
- 使用非连续内存块管理KV Cache
- 减少内存碎片
- 提高缓存分配与管理效率
- 支持更灵活的缓存共享
- 注意力架构优化
- Local Windowed Attention
- 限制注意力窗口
- 减少需要处理或缓存的历史信息
- Multi-Query Attention(MQA)
- 多个Query头共享一组Key和Value
- Grouped-Query Attention(GQA)
- 多个Query头分组共享Key和Value
- Cross-Layer Attention
- 在特定架构中跨层共享部分注意力信息
- Local Windowed Attention
- KV Cache Quantization
- 注意
- 架构优化通常需要在模型设计、训练或微调阶段处理
- PagedAttention主要优化内存管理,不等于KV Cache压缩
- 先判断
- 大量重复Prompt导致重复计算
- 适用场景
- 多个请求共享相同System Prompt
- 多个请求重复使用长文档前缀
- 多轮对话包含可复用的历史前缀
- 候选技术
- Prompt Caching
- 也称Prefix Caching或Context Caching
- 识别可复用的Prompt前缀
- 缓存对应的计算结果
- 新请求命中缓存后复用已有结果
- 只计算尚未缓存的部分
- Prompt Caching
- 收益
- 减少重复Prefill计算
- 降低首Token延迟
- 降低重复输入的计算成本
- 局限
- 需要缓存空间
- 需要管理缓存生命周期
- 收益取决于缓存命中率与可复用范围
- 适用场景
- 吞吐量不足
- 先判断
- 请求吞吐量还是Token吞吐量不足
- 系统是否受到计算、内存或排队限制
- 当前Batch Size是否合理
- 请求长度与到达速率如何分布
- 候选技术
- Batching
- Static Batching
- 固定数量的请求组成Batch
- 实现简单
- 可能需要等待批次凑齐
- Dynamic Batching
- 设置最大Batch Size
- 设置最大等待时间
- 达到条件后执行
- 在批处理效率与等待时间之间权衡
- Static Batching
- Continuous Batching
- 在推理执行过程中动态加入和移除请求
- 请求完成后释放相应位置
- 允许新请求加入后续执行步骤
- 减少请求之间的阻塞
- 提高硬件资源利用效率
- Replica Parallelism
- 部署多个完整模型副本
- 分担不同请求
- 增加并发处理能力
- 需要额外硬件资源
- Batching
- 注意
- 批处理不一定能改善所有类型的延迟
- 应同时检查Goodput和高分位延迟
- 先判断
- Prefill与Decode互相争用资源
- 问题
- Prefill与Decode的资源需求不同
- 两者同时运行可能互相干扰
- 候选技术
- Prefill/Decode Disaggregation
- Prefill运行在独立实例
- Decode运行在独立实例
- 传输必要的KV Cache等中间状态
- Prefill/Decode Disaggregation
- 收益
- 减少不同阶段之间的资源干扰
- 可以分别优化TTFT与TPOT
- 便于独立配置资源
- 代价
- 增加通信开销
- 增加调度复杂度
- 需要考虑KV Cache传输成本
- 适用性
- 需要结合负载特征与系统架构评估
- 问题
- 单设备无法部署模型
- 先判断
- 模型权重是否超出单设备内存
- KV Cache与运行时数据是否超出内存
- 目标是支持模型部署还是提高吞吐量
- 候选技术
- Tensor Parallelism
- 将张量运算拆分到多个设备
- 支持更大模型部署
- 可能降低部分计算延迟
- 存在设备间通信开销
- Pipeline Parallelism
- 将模型划分为多个阶段
- 不同阶段部署在不同设备
- 可通过Micro-batch实现阶段间计算重叠
- 支持大模型部署
- 可能增加单请求延迟
- 存在阶段间通信与流水线空闲
- Quantization
- 降低模型权重占用
- 在满足质量要求时帮助模型装入单设备
- Tensor Parallelism
- 注意
- 模型并行首先解决模型拆分与部署问题
- 是否提升延迟或吞吐量取决于并行策略与通信开销
- 先判断
- 高并发导致资源不足
- 先判断
- 是否存在请求排队
- 是否受到GPU计算能力限制
- 是否受到内存容量限制
- 是否存在调度效率问题
- 候选技术
- Replica Parallelism
- 增加模型副本
- 分担请求负载
- 提高整体处理能力
- 增加硬件成本
- Continuous Batching
- 提高请求调度与批处理效率
- 减少请求之间的阻塞
- PagedAttention
- 提高KV Cache的内存管理效率
- 可能支持更高的并发请求数量
- Replica Parallelism
- 注意
- 高并发是工作负载特征,不是单一的硬件瓶颈
- 需要结合计算、内存、排队和成本综合判断
- 先判断
- 计算内核效率不足
- 先判断
- 计算资源是否未被充分利用
- 算子执行是否存在大量启动开销
- 是否存在冗余的中间数据读写
- 是否存在低效的内存访问模式
- 候选技术
- Kernel Optimization
- Vectorization
- 同时处理多个数据元素
- Parallelization
- 将独立计算分配给多个执行单元
- Loop Tiling
- 根据缓存和内存布局调整计算分块
- Operator Fusion
- 合并多个计算操作
- 减少中间数据读写与算子启动开销
- Vectorization
- Compiler Optimization
- Lowering
- 算子转换
- 选择或生成优化内核
- 根据目标硬件调整执行方式
- 相关技术
- CUDA
- Triton
- ROCm
- torch.compile
- XLA
- TensorRT
- Apache TVM
- MLIR
- Kernel Optimization
- 注意
- Kernel是底层计算执行单元
- Compiler负责将计算图或算子转换为目标执行形式
- 具体优化效果取决于模型、硬件和编译结果
- 先判断
- 其他工作负载问题
- 长上下文计算量大
- 分析注意力计算与KV Cache开销
- 考虑注意力计算优化和架构优化
- 请求处理能力不足
- 分析请求调度、资源利用率与请求分布
- 考虑批处理、并行部署与扩容
- 成本过高
- 分析单位请求和单位Token成本
- 考虑量化、批处理、缓存复用与资源配置
- 长上下文计算量大
- 模型权重占用过大
- 4.5 验证优化效果
- 建立优化前的基线
- 记录TTFT
- 记录TPOT与总响应时间
- 记录p50、p95、p99等延迟分位数
- 记录请求吞吐量与Token吞吐量
- 记录Goodput
- 记录GPU Utilization、MFU和MBU等资源指标
- 记录单位请求或单位Token成本
- 记录模型质量评估结果
- 控制实验条件
- 使用相同或可比较的测试数据
- 控制输入长度与输出长度
- 控制并发量和请求到达速率
- 明确硬件配置与模型版本
- 明确统计窗口与指标口径
- 比较优化前后的结果
- 延迟是否降低
- 吞吐量是否提高
- Goodput是否提高
- 资源使用是否改善
- 成本是否降低
- 模型质量是否满足要求
- 检查副作用
- 是否增加高分位延迟
- 是否增加内存占用
- 是否增加通信或调度开销
- 是否降低模型质量
- 是否引入新的性能瓶颈
- 判断优化是否成功
- 原有瓶颈是否得到改善
- 目标指标是否达到要求
- 是否引入不可接受的成本或质量损失
- 是否需要继续分析新的瓶颈
- 建立优化前的基线
拖动可平移,滚轮缩放,点击节点可展开或折叠。大型导图默认折叠较深层级,可点击节点继续展开。
讨论
使用 GitHub 账号参与讨论,评论会保存在 GitHub Issues 中。在 GitHub 查看