
摘要
推理引擎是大模型落地的核心基础设施。本文从 vLLM、SGLang、TensorRT-LLM、llama.cpp 四大主流引擎的架构原理、核心优化、性能对比、选型决策四个切口,给出源码级实现与企业级推理服务决策框架。
1. vLLM:PagedAttention 与吞吐优化
vLLM 由 UC Berkeley 提出,原创 PagedAttention 与 Continuous Batching,成为高吞吐推理的事实标准。其核心贡献是显存碎片治理与 GPU 持续满载。
#mermaid-svg-IuxhlU5vgHIaiNJ4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .error-icon{fill:#552222;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .marker.cross{stroke:#333333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 p{margin:0;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster-label text{fill:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster-label span{color:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster-label span p{background-color:transparent;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .label text,#mermaid-svg-IuxhlU5vgHIaiNJ4 span{fill:#333;color:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .node rect,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node circle,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node ellipse,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node polygon,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .rough-node .label text,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node .label text,#mermaid-svg-IuxhlU5vgHIaiNJ4 .image-shape .label,#mermaid-svg-IuxhlU5vgHIaiNJ4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .rough-node .label,#mermaid-svg-IuxhlU5vgHIaiNJ4 .node .label,#mermaid-svg-IuxhlU5vgHIaiNJ4 .image-shape .label,#mermaid-svg-IuxhlU5vgHIaiNJ4 .icon-shape .label{text-align:center;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .node.clickable{cursor:pointer;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .arrowheadPath{fill:#333333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IuxhlU5vgHIaiNJ4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IuxhlU5vgHIaiNJ4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster text{fill:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .cluster span{color:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IuxhlU5vgHIaiNJ4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .icon-shape,#mermaid-svg-IuxhlU5vgHIaiNJ4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .icon-shape p,#mermaid-svg-IuxhlU5vgHIaiNJ4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .icon-shape .label rect,#mermaid-svg-IuxhlU5vgHIaiNJ4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IuxhlU5vgHIaiNJ4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IuxhlU5vgHIaiNJ4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-IuxhlU5vgHIaiNJ4 .default tspan{fill:#000000!important;} vLLM 架构
PagedAttention: KV Cache分页
Continuous Batching: 动态批
Prefix Caching: 共享前缀缓存
Tensor Parallel: 多卡并行
显存利用率 60%->96%
GPU利用率 40%->85%
首token延迟降80%
多卡线性加速
python
# 来源:vLLM 引擎核心 / vLLM 0.4
from dataclasses import dataclass
from typing import List, Dict
import torch
@dataclass
class Request:
request_id: int
prompt: str
max_tokens: int
output: List[int] = None
finished: bool = False
class VLLMEngine:
"""vLLM 推理引擎核心"""
def __init__(self, model_path, tensor_parallel=1, gpu_memory_utilization=0.9):
self.model = self._load_model(model_path, tensor_parallel)
# PagedAttention KV Cache 管理器
self.kv_cache = PagedKVCache(
n_layers=self.model.config.n_layers,
n_heads=self.model.config.n_kv_heads,
d_head=self.model.config.d_head,
block_size=16,
total_blocks=self._estimate_blocks(gpu_memory_utilization),
)
# Continuous Batching 调度器
self.scheduler = ContinuousBatcher(max_batch=256)
# Prefix Caching
self.prefix_cache = PrefixCache()
def generate(self, requests: List[Request]):
"""批量生成"""
# 1. 加入调度队列
for req in requests:
self.scheduler.add_request(req)
# 2. 循环调度直至全部完成
while self.scheduler.has_pending():
batch = self.scheduler.step()
outputs = self.model.forward(batch, self.kv_cache)
self.scheduler.update(outputs)
return [r.output for r in requests]
def _estimate_blocks(self, utilization):
# 预留显存 = 总显存 * utilization - 模型权重
total_mem = torch.cuda.get_device_properties(0).total_memory
model_mem = self.model.memory_footprint
kv_mem = total_mem * utilization - model_mem
block_mem = 16 * self.model.config.n_layers * 2 * \
self.model.config.n_kv_heads * self.model.config.d_head * 2
return int(kv_mem / block_mem)
def _load_model(self, path, tp):
return DummyModel() # 占位, 实际用 transformers 加载
class PagedKVCache:
"""PagedAttention KV Cache (简化版)"""
def __init__(self, n_layers, n_heads, d_head, block_size, total_blocks):
self.block_size = block_size
self.blocks = torch.zeros(
total_blocks, n_layers, 2, block_size, n_heads, d_head,
dtype=torch.float16, device='cuda')
self.free = list(range(total_blocks))
self.tables = {}
def allocate(self, req_id, n_tokens):
n_blocks = (n_tokens + self.block_size - 1) // self.block_size
blocks = [self.free.pop() for _ in range(n_blocks)]
self.tables[req_id] = blocks
# 量化: LLaMA-2-7B A100 40GB
# 传统引擎: batch=32, 2000 tokens/s
# vLLM: batch=256, 6000 tokens/s (3倍)
# 关键: PagedAttention 使 batch 从 32 提升至 256
量化:LLaMA-2-7B 在 A100 40GB 上,传统引擎 batch=32 吞吐 2000 tokens/s,vLLM batch=256 吞吐 6000 tokens/s(3 倍)。PagedAttention 使显存利用率从 60% 升至 96%,batch 从 32 提升至 256。GPU 利用率从 40% 升至 85%。
边界:vLLM 对非标准架构支持滞后------新模型需等社区适配 KV Cache 接口。PagedAttention 的块表间接寻址有 5-10% 带宽损失------需自定义 CUDA kernel 优化。Tensor Parallel 通信开销在 4 卡以上显著------7B 模型 4 卡 TP 加速比仅 2.8 倍。
2. SGLang:RadixAttention 与结构化输出
SGLang 同样出自 LMSYS,针对结构化生成场景优化。原创 RadixAttention(基数树前缀缓存)与约束解码集成,在多轮对话与 Agent 场景表现突出。
#mermaid-svg-qKBDpKMswkZP8z2O{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qKBDpKMswkZP8z2O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qKBDpKMswkZP8z2O .error-icon{fill:#552222;}#mermaid-svg-qKBDpKMswkZP8z2O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qKBDpKMswkZP8z2O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qKBDpKMswkZP8z2O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qKBDpKMswkZP8z2O .marker.cross{stroke:#333333;}#mermaid-svg-qKBDpKMswkZP8z2O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qKBDpKMswkZP8z2O p{margin:0;}#mermaid-svg-qKBDpKMswkZP8z2O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qKBDpKMswkZP8z2O .cluster-label text{fill:#333;}#mermaid-svg-qKBDpKMswkZP8z2O .cluster-label span{color:#333;}#mermaid-svg-qKBDpKMswkZP8z2O .cluster-label span p{background-color:transparent;}#mermaid-svg-qKBDpKMswkZP8z2O .label text,#mermaid-svg-qKBDpKMswkZP8z2O span{fill:#333;color:#333;}#mermaid-svg-qKBDpKMswkZP8z2O .node rect,#mermaid-svg-qKBDpKMswkZP8z2O .node circle,#mermaid-svg-qKBDpKMswkZP8z2O .node ellipse,#mermaid-svg-qKBDpKMswkZP8z2O .node polygon,#mermaid-svg-qKBDpKMswkZP8z2O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qKBDpKMswkZP8z2O .rough-node .label text,#mermaid-svg-qKBDpKMswkZP8z2O .node .label text,#mermaid-svg-qKBDpKMswkZP8z2O .image-shape .label,#mermaid-svg-qKBDpKMswkZP8z2O .icon-shape .label{text-anchor:middle;}#mermaid-svg-qKBDpKMswkZP8z2O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qKBDpKMswkZP8z2O .rough-node .label,#mermaid-svg-qKBDpKMswkZP8z2O .node .label,#mermaid-svg-qKBDpKMswkZP8z2O .image-shape .label,#mermaid-svg-qKBDpKMswkZP8z2O .icon-shape .label{text-align:center;}#mermaid-svg-qKBDpKMswkZP8z2O .node.clickable{cursor:pointer;}#mermaid-svg-qKBDpKMswkZP8z2O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qKBDpKMswkZP8z2O .arrowheadPath{fill:#333333;}#mermaid-svg-qKBDpKMswkZP8z2O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qKBDpKMswkZP8z2O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qKBDpKMswkZP8z2O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qKBDpKMswkZP8z2O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qKBDpKMswkZP8z2O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qKBDpKMswkZP8z2O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qKBDpKMswkZP8z2O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qKBDpKMswkZP8z2O .cluster text{fill:#333;}#mermaid-svg-qKBDpKMswkZP8z2O .cluster span{color:#333;}#mermaid-svg-qKBDpKMswkZP8z2O div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qKBDpKMswkZP8z2O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qKBDpKMswkZP8z2O rect.text{fill:none;stroke-width:0;}#mermaid-svg-qKBDpKMswkZP8z2O .icon-shape,#mermaid-svg-qKBDpKMswkZP8z2O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qKBDpKMswkZP8z2O .icon-shape p,#mermaid-svg-qKBDpKMswkZP8z2O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qKBDpKMswkZP8z2O .icon-shape .label rect,#mermaid-svg-qKBDpKMswkZP8z2O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qKBDpKMswkZP8z2O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qKBDpKMswkZP8z2O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qKBDpKMswkZP8z2O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-qKBDpKMswkZP8z2O .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-qKBDpKMswkZP8z2O .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-qKBDpKMswkZP8z2O .default tspan{fill:#000000!important;} SGLang 架构
RadixAttention: 基数树缓存
约束解码: 正则/JSON原生支持
多轮对话: 共享历史前缀
Function Call: 工具调用优化
基数树索引前缀
多轮对话命中率 80%+
JSON合法率 100%
多轮延迟稳定
python
# 来源:SGLang RadixAttention / SGLang 0.3
import torch
from collections import defaultdict
class RadixAttention:
"""基数树前缀缓存: 共享前缀的 KV Cache"""
def __init__(self):
self.tree = {} # 基数树: token序列 -> kv_cache
self.stats = {'hit': 0, 'miss': 0}
def get_or_compute(self, token_ids, model):
"""获取或计算前缀 KV Cache"""
# 1. 在基数树中找最长匹配前缀
prefix, cached_kv = self._longest_prefix(token_ids)
if prefix:
self.stats['hit'] += 1
else:
self.stats['miss'] += 1
# 2. 仅计算未缓存部分
new_tokens = token_ids[len(prefix):]
if new_tokens:
new_kv = model.prefill(new_tokens, cached_kv)
# 3. 更新基数树
full = tuple(token_ids)
self.tree[full] = model.merge_kv(cached_kv, new_kv)
return self.tree[full]
return cached_kv
def _longest_prefix(self, token_ids):
"""找最长匹配前缀"""
for length in range(len(token_ids), 0, -1):
prefix = tuple(token_ids[:length])
if prefix in self.tree:
return list(prefix), self.tree[prefix]
return [], None
# 量化: 多轮对话场景 RadixAttention 命中率 80%+
# 每轮仅算新增 token, 首 token 延迟降 75%
# 对比 vLLM Prefix Cache: 基数树支持部分匹配, 命中率更高
python
# 来源:SGLang 约束解码 / SGLang 0.3
import re
import torch.nn.functional as F
class ConstrainedGenerator:
"""SGLang 约束解码: 正则/JSON 原生支持"""
def __init__(self, model, regex_pattern=None, json_schema=None):
self.model = model
self.regex = re.compile(regex_pattern) if regex_pattern else None
self.schema = json_schema
def generate(self, prompt, max_tokens=256):
tokens = self.model.encode(prompt)
# 编译约束为状态机
fsm = self._compile_constraint()
for _ in range(max_tokens):
logits = self.model.forward(tokens)
# 约束过滤: 仅保留 FSM 合法 token
legal_ids = fsm.next_legal_tokens(self._decode(tokens))
mask = torch.full_like(logits, float('-inf'))
mask[legal_ids] = 0
logits = logits + mask
next_token = torch.argmax(logits, dim=-1)
tokens = torch.cat([tokens, next_token.unsqueeze(0)])
if fsm.is_accepting(self._decode(tokens)):
break
return self._decode(tokens)
def _compile_constraint(self):
if self.regex:
return RegexFSM(self.regex)
elif self.schema:
return JSONSchemaFSM(self.schema)
return None
# 量化: SGLang 约束解码 JSON 合法率 100%
# 比 vLLM + outlines 快 20% (原生集成无额外开销)
# Agent 多轮工具调用场景延迟降 40%
量化:多轮对话场景 RadixAttention 命中率 80%+,首 token 延迟降 75%。基数树支持部分匹配,比 vLLM Prefix Cache 命中率高 15%。约束解码 JSON 合法率 100%,比 vLLM+outlines 快 20%(原生集成无额外开销)。Agent 多轮工具调用延迟降 40%。
边界:RadixAttention 的基数树内存开销随对话轮数增长------长对话需定期淘汰冷节点。约束解码的 FSM 编译有一次性开销------短生成任务不划算。SGLang 生态比 vLLM 小------社区支持与模型适配滞后。
3. TensorRT-LLM:NVIDIA 定制延迟优化
TensorRT-LLM 是 NVIDIA 官方推理引擎,用定制 CUDA kernel 与图优化实现极致延迟。适合对延迟敏感的实时场景,代价是需离线编译且仅支持 NVIDIA GPU。
#mermaid-svg-IDNuFfSfqo7RFl6x{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IDNuFfSfqo7RFl6x .error-icon{fill:#552222;}#mermaid-svg-IDNuFfSfqo7RFl6x .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IDNuFfSfqo7RFl6x .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IDNuFfSfqo7RFl6x .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IDNuFfSfqo7RFl6x .marker.cross{stroke:#333333;}#mermaid-svg-IDNuFfSfqo7RFl6x svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IDNuFfSfqo7RFl6x p{margin:0;}#mermaid-svg-IDNuFfSfqo7RFl6x .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster-label text{fill:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster-label span{color:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster-label span p{background-color:transparent;}#mermaid-svg-IDNuFfSfqo7RFl6x .label text,#mermaid-svg-IDNuFfSfqo7RFl6x span{fill:#333;color:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x .node rect,#mermaid-svg-IDNuFfSfqo7RFl6x .node circle,#mermaid-svg-IDNuFfSfqo7RFl6x .node ellipse,#mermaid-svg-IDNuFfSfqo7RFl6x .node polygon,#mermaid-svg-IDNuFfSfqo7RFl6x .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IDNuFfSfqo7RFl6x .rough-node .label text,#mermaid-svg-IDNuFfSfqo7RFl6x .node .label text,#mermaid-svg-IDNuFfSfqo7RFl6x .image-shape .label,#mermaid-svg-IDNuFfSfqo7RFl6x .icon-shape .label{text-anchor:middle;}#mermaid-svg-IDNuFfSfqo7RFl6x .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IDNuFfSfqo7RFl6x .rough-node .label,#mermaid-svg-IDNuFfSfqo7RFl6x .node .label,#mermaid-svg-IDNuFfSfqo7RFl6x .image-shape .label,#mermaid-svg-IDNuFfSfqo7RFl6x .icon-shape .label{text-align:center;}#mermaid-svg-IDNuFfSfqo7RFl6x .node.clickable{cursor:pointer;}#mermaid-svg-IDNuFfSfqo7RFl6x .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IDNuFfSfqo7RFl6x .arrowheadPath{fill:#333333;}#mermaid-svg-IDNuFfSfqo7RFl6x .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IDNuFfSfqo7RFl6x .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IDNuFfSfqo7RFl6x .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IDNuFfSfqo7RFl6x .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IDNuFfSfqo7RFl6x .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IDNuFfSfqo7RFl6x .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster text{fill:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x .cluster span{color:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IDNuFfSfqo7RFl6x .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IDNuFfSfqo7RFl6x rect.text{fill:none;stroke-width:0;}#mermaid-svg-IDNuFfSfqo7RFl6x .icon-shape,#mermaid-svg-IDNuFfSfqo7RFl6x .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IDNuFfSfqo7RFl6x .icon-shape p,#mermaid-svg-IDNuFfSfqo7RFl6x .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IDNuFfSfqo7RFl6x .icon-shape .label rect,#mermaid-svg-IDNuFfSfqo7RFl6x .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IDNuFfSfqo7RFl6x .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IDNuFfSfqo7RFl6x .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IDNuFfSfqo7RFl6x :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-IDNuFfSfqo7RFl6x .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-IDNuFfSfqo7RFl6x .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-IDNuFfSfqo7RFl6x .default tspan{fill:#000000!important;} TensorRT-LLM 架构
定制CUDA kernel
图优化: 算子融合
INT8/FP8量化
In-flight batching
FlashAttention定制
MMHA kernel融合
算子融合降kernel launch
显存降50%+速度提升
动态批+优先级调度
python
# 来源:TensorRT-LLM 编译流程 / TensorRT-LLM 0.8
import tensorrt as trt
import torch
class TRTLLMBuilder:
"""TensorRT-LLM 引擎编译器"""
def __init__(self, model_path, precision='fp16'):
self.model_path = model_path
self.precision = precision
def build(self, output_engine_path, max_batch=256, max_seq=4096):
"""离线编译引擎 (耗时 30 分钟)"""
# 1. 加载模型权重
weights = self._load_weights(self.model_path)
# 2. 构建计算图
network = self._build_network(weights, max_batch, max_seq)
# 3. 图优化: 算子融合
builder = trt.Builder(trt.Logger())
config = builder.create_builder_config()
config.set_flag(trt.BuilderFlag.FP16 if self.precision == 'fp16'
else trt.BuilderFlag.INT8)
# 4. 优化 plugin: FlashAttention, MMHA
plugin = self._register_plugins()
# 5. 编译为引擎
engine = builder.build_engine(network, config)
# 6. 序列化保存
with open(output_engine_path, 'wb') as f:
f.write(engine.serialize())
def _build_network(self, weights, max_batch, max_seq):
"""构建 Transformer 计算图"""
# 实际用 TensorRT API 逐层构建
# 关键优化: FlashAttention plugin, MMHA (Multi-Head Attention融合)
return None
def _register_plugins(self):
"""注册定制 plugin"""
# FlashAttention: 融合 QKV投影+Attention+输出投影
# MMHA: 单 kernel 完成多层 Attention
# CrossAttention: 融合跨注意力
return None
# 量化: 编译耗时 30 分钟 (7B), 70B 需 2 小时
# 编译后引擎不可移植: 仅同架构GPU可用
# 速度: 比 vLLM 快 1.5-2 倍 (延迟维度)
python
# 来源:TensorRT-LLM 推理服务 / TensorRT-LLM 0.8
class TRTLLMServer:
"""TensorRT-LLM 推理服务"""
def __init__(self, engine_path):
# 加载预编译引擎
with open(engine_path, 'rb') as f:
self.engine = self._deserialize(f.read())
self.context = self.engine.create_execution_context()
def generate(self, prompts, max_tokens=256):
"""批量推理 (In-flight batching)"""
# In-flight batching: 请求到达即调度, 无需等batch满
results = []
for prompt in prompts:
input_ids = self._encode(prompt)
# 设置动态 shape
self.context.set_input_shape('input_ids', input_ids.shape)
# 执行
output = self._execute(input_ids, max_tokens)
results.append(self._decode(output))
return results
def _execute(self, input_ids, max_tokens):
"""执行引擎"""
# 定制 kernel: 无 Python 开销
output = torch.zeros(max_tokens, dtype=torch.int32, device='cuda')
self.context.execute_async_v2([input_ids.data_ptr(), output.data_ptr()])
return output
# 量化 (LLaMA-2-7B A100):
# 引擎 P50延迟(ms) P99(ms) 吞吐(tokens/s)
# vLLM 80 200 6000
# SGLang 85 210 5500
# TensorRT-LLM 40 90 5500
# TensorRT-LLM 延迟最优, 吞吐略低于 vLLM
量化(LLaMA-2-7B A100):TensorRT-LLM P50 40ms、P99 90ms 延迟最优,吞吐 5500 tokens/s。比 vLLM 延迟降 50%,但吞吐略低 8%。INT8 量化额外提速 30%,显存降 50%。编译耗时 30 分钟(7B)至 2 小时(70B)。
边界:编译后引擎不可移植------仅同架构 GPU 可用,换卡需重编译。模型架构变更需重编译------微调后权重变需重新 build。仅支持 NVIDIA GPU------AMD/Intel GPU 不可用。定制 kernel 对新架构支持滞后------H100 上市后 3 个月才优化。
4. llama.cpp:CPU 与边缘部署
llama.cpp 是纯 C++ 实现的推理引擎,支持 CPU 推理与 GGUF 量化格式,适合边缘设备、个人设备、无 GPU 场景。
#mermaid-svg-6qXW94XhV2cDV7Ao{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6qXW94XhV2cDV7Ao .error-icon{fill:#552222;}#mermaid-svg-6qXW94XhV2cDV7Ao .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6qXW94XhV2cDV7Ao .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6qXW94XhV2cDV7Ao .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6qXW94XhV2cDV7Ao .marker.cross{stroke:#333333;}#mermaid-svg-6qXW94XhV2cDV7Ao svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6qXW94XhV2cDV7Ao p{margin:0;}#mermaid-svg-6qXW94XhV2cDV7Ao .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster-label text{fill:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster-label span{color:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster-label span p{background-color:transparent;}#mermaid-svg-6qXW94XhV2cDV7Ao .label text,#mermaid-svg-6qXW94XhV2cDV7Ao span{fill:#333;color:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao .node rect,#mermaid-svg-6qXW94XhV2cDV7Ao .node circle,#mermaid-svg-6qXW94XhV2cDV7Ao .node ellipse,#mermaid-svg-6qXW94XhV2cDV7Ao .node polygon,#mermaid-svg-6qXW94XhV2cDV7Ao .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6qXW94XhV2cDV7Ao .rough-node .label text,#mermaid-svg-6qXW94XhV2cDV7Ao .node .label text,#mermaid-svg-6qXW94XhV2cDV7Ao .image-shape .label,#mermaid-svg-6qXW94XhV2cDV7Ao .icon-shape .label{text-anchor:middle;}#mermaid-svg-6qXW94XhV2cDV7Ao .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6qXW94XhV2cDV7Ao .rough-node .label,#mermaid-svg-6qXW94XhV2cDV7Ao .node .label,#mermaid-svg-6qXW94XhV2cDV7Ao .image-shape .label,#mermaid-svg-6qXW94XhV2cDV7Ao .icon-shape .label{text-align:center;}#mermaid-svg-6qXW94XhV2cDV7Ao .node.clickable{cursor:pointer;}#mermaid-svg-6qXW94XhV2cDV7Ao .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6qXW94XhV2cDV7Ao .arrowheadPath{fill:#333333;}#mermaid-svg-6qXW94XhV2cDV7Ao .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6qXW94XhV2cDV7Ao .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6qXW94XhV2cDV7Ao .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6qXW94XhV2cDV7Ao .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6qXW94XhV2cDV7Ao .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6qXW94XhV2cDV7Ao .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster text{fill:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao .cluster span{color:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6qXW94XhV2cDV7Ao .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6qXW94XhV2cDV7Ao rect.text{fill:none;stroke-width:0;}#mermaid-svg-6qXW94XhV2cDV7Ao .icon-shape,#mermaid-svg-6qXW94XhV2cDV7Ao .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6qXW94XhV2cDV7Ao .icon-shape p,#mermaid-svg-6qXW94XhV2cDV7Ao .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6qXW94XhV2cDV7Ao .icon-shape .label rect,#mermaid-svg-6qXW94XhV2cDV7Ao .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6qXW94XhV2cDV7Ao .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6qXW94XhV2cDV7Ao .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6qXW94XhV2cDV7Ao :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-6qXW94XhV2cDV7Ao .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-6qXW94XhV2cDV7Ao .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-6qXW94XhV2cDV7Ao .default tspan{fill:#000000!important;} llama.cpp 架构
纯C++实现
GGUF量化: Q4_K_M等
CPU+GPU混合
内存映射加载
无依赖, 单文件
7B模型Q4仅4GB
部分层GPU+部分CPU
大模型按需加载
python
# 来源:llama.cpp 量化格式 / llama.cpp b2000
# GGUF 量化级别对比 (LLaMA-2-7B):
# F16: 13.5 GB, 困惑度 5.68 (基准)
# Q8_0: 7.2 GB, 困惑度 5.72 (损失0.04)
# Q6_K: 5.5 GB, 困惑度 5.78 (损失0.10)
# Q5_K_M: 4.8 GB, 困惑度 5.84 (损失0.16)
# Q4_K_M: 4.1 GB, 困惑度 5.91 (损失0.23)
# Q3_K_M: 3.3 GB, 困惑度 6.15 (损失0.47)
# Q2_K: 2.7 GB, 困惑度 6.65 (损失0.97, 不推荐)
class GGUFQuantizer:
"""GGUF 量化器 (概念实现)"""
def __init__(self, model, quant_type='Q4_K_M'):
self.model = model
self.quant = quant_type
def quantize(self, output_path):
"""量化模型为 GGUF 格式"""
# 1. 遍历所有权重张量
for name, tensor in self.model.named_parameters():
if 'weight' in name and tensor.dim() >= 2:
# 2. 分块量化 (块大小 32 或 256)
quantized = self._quant_block(tensor, self.quant)
self._write_block(output_path, name, quantized)
else:
# 非权重 (bias, norm) 保持 FP16
self._write_fp16(output_path, name, tensor)
def _quant_block(self, tensor, qtype):
"""分块量化"""
# Q4_K_M: 4 bit 主权重 + 6 bit 缩放因子
# 块大小 256, 每块有 6 个缩放级别
block_size = 256
blocks = tensor.split(block_size)
quantized = []
for block in blocks:
# 计算块缩放因子
scale = block.abs().max() / 7.0 # 4bit 范围 -8~7
# 量化: fp16 -> int4
q = (block / scale).round().clamp(-8, 7).to(torch.int8)
quantized.append((q, scale))
return quantized
import torch
# 量化: Q4_K_M 是质量/大小最优平衡点
# 7B 模型 4.1GB 可在 8GB 内存笔记本运行
# 速度: M2 MacBook 10 tokens/s (7B Q4)
python
# 来源:llama.cpp 推理调用 / llama.cpp b2000
import subprocess
class LlamaCppRunner:
"""llama.cpp 推理调用器"""
def __init__(self, model_path, n_ctx=2048, n_threads=8, n_gpu_layers=0):
self.model = model_path
self.ctx = n_ctx
self.threads = n_threads
self.gpu_layers = n_gpu_layers # GPU 层数 (0=纯CPU)
def generate(self, prompt, max_tokens=256, temperature=0.7):
"""调用 llama.cpp 二进制"""
cmd = [
'./main', '-m', self.model,
'-p', prompt,
'-n', str(max_tokens),
'-t', str(self.threads),
'-c', str(self.ctx),
'--temp', str(temperature),
'-ngl', str(self.gpu_layers),
]
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
# 量化 (LLaMA-2-7B Q4_K_M):
# 硬件 速度(tokens/s) 延迟(ms/token)
# M2 MacBook Air 10 100
# Intel i7-12700H 8 125
# RTX 4090 (全GPU) 120 8
# 树莓派5 2 500
# 关键: 边缘设备可用, 但延迟高, 仅适合离线/低并发
量化(LLaMA-2-7B Q4_K_M):模型仅 4.1GB,可在 8GB 内存笔记本运行。M2 MacBook 10 tokens/s,Intel i7 8 tokens/s,RTX 4090 全 GPU 120 tokens/s,树莓派 5 仅 2 tokens/s。Q4_K_M 困惑度损失 0.23 可接受,Q2_K 损失 0.97 不推荐。
边界:CPU 推理速度受限------7B 模型笔记本 10 tokens/s,不适合高并发在线服务。GGUF 量化对部分架构支持不全------MoE 模型量化质量损失大。GPU 混合层设置需手动调------n_gpu_layers 过高致显存溢出,过低速度慢。
5. 分布式推理:张量并行与流水并行
单卡显存无法容纳大模型(70B 需 140GB FP16),需多卡并行。张量并行(TP)切分矩阵到多卡同步计算,流水并行(PP)切分层到多卡异步流水。两者结合实现 70B+ 模型推理。
#mermaid-svg-q0mddmCfkxipPSFH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-q0mddmCfkxipPSFH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-q0mddmCfkxipPSFH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-q0mddmCfkxipPSFH .error-icon{fill:#552222;}#mermaid-svg-q0mddmCfkxipPSFH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-q0mddmCfkxipPSFH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-q0mddmCfkxipPSFH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-q0mddmCfkxipPSFH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-q0mddmCfkxipPSFH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-q0mddmCfkxipPSFH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-q0mddmCfkxipPSFH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-q0mddmCfkxipPSFH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-q0mddmCfkxipPSFH .marker.cross{stroke:#333333;}#mermaid-svg-q0mddmCfkxipPSFH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-q0mddmCfkxipPSFH p{margin:0;}#mermaid-svg-q0mddmCfkxipPSFH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-q0mddmCfkxipPSFH .cluster-label text{fill:#333;}#mermaid-svg-q0mddmCfkxipPSFH .cluster-label span{color:#333;}#mermaid-svg-q0mddmCfkxipPSFH .cluster-label span p{background-color:transparent;}#mermaid-svg-q0mddmCfkxipPSFH .label text,#mermaid-svg-q0mddmCfkxipPSFH span{fill:#333;color:#333;}#mermaid-svg-q0mddmCfkxipPSFH .node rect,#mermaid-svg-q0mddmCfkxipPSFH .node circle,#mermaid-svg-q0mddmCfkxipPSFH .node ellipse,#mermaid-svg-q0mddmCfkxipPSFH .node polygon,#mermaid-svg-q0mddmCfkxipPSFH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-q0mddmCfkxipPSFH .rough-node .label text,#mermaid-svg-q0mddmCfkxipPSFH .node .label text,#mermaid-svg-q0mddmCfkxipPSFH .image-shape .label,#mermaid-svg-q0mddmCfkxipPSFH .icon-shape .label{text-anchor:middle;}#mermaid-svg-q0mddmCfkxipPSFH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-q0mddmCfkxipPSFH .rough-node .label,#mermaid-svg-q0mddmCfkxipPSFH .node .label,#mermaid-svg-q0mddmCfkxipPSFH .image-shape .label,#mermaid-svg-q0mddmCfkxipPSFH .icon-shape .label{text-align:center;}#mermaid-svg-q0mddmCfkxipPSFH .node.clickable{cursor:pointer;}#mermaid-svg-q0mddmCfkxipPSFH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-q0mddmCfkxipPSFH .arrowheadPath{fill:#333333;}#mermaid-svg-q0mddmCfkxipPSFH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-q0mddmCfkxipPSFH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-q0mddmCfkxipPSFH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q0mddmCfkxipPSFH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-q0mddmCfkxipPSFH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q0mddmCfkxipPSFH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-q0mddmCfkxipPSFH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-q0mddmCfkxipPSFH .cluster text{fill:#333;}#mermaid-svg-q0mddmCfkxipPSFH .cluster span{color:#333;}#mermaid-svg-q0mddmCfkxipPSFH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-q0mddmCfkxipPSFH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-q0mddmCfkxipPSFH rect.text{fill:none;stroke-width:0;}#mermaid-svg-q0mddmCfkxipPSFH .icon-shape,#mermaid-svg-q0mddmCfkxipPSFH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q0mddmCfkxipPSFH .icon-shape p,#mermaid-svg-q0mddmCfkxipPSFH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-q0mddmCfkxipPSFH .icon-shape .label rect,#mermaid-svg-q0mddmCfkxipPSFH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q0mddmCfkxipPSFH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-q0mddmCfkxipPSFH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-q0mddmCfkxipPSFH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-q0mddmCfkxipPSFH .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-q0mddmCfkxipPSFH .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-q0mddmCfkxipPSFH .default tspan{fill:#000000!important;} 分布式推理
张量并行 TP
流水并行 PP
专家并行 EP
切矩阵到多卡
同步通信: AllReduce
延迟低, 显存均分
切层到多卡
异步流水: micro-batch
通信少, 但流水气泡
MoE专家切多卡
All-to-All通信
python
# 来源:张量并行实现 / Megatron-LM 4.0
import torch
import torch.distributed as dist
class TensorParallelAttention:
"""张量并行 Attention (列并行 QKV + 行并行输出)"""
def __init__(self, d_model, n_heads, tp_size, rank):
self.d_model = d_model
self.n_heads = n_heads
self.tp_size = tp_size # 并行卡数
self.rank = rank # 当前卡 ID
# 每卡仅负责 n_heads/tp_size 个头
self.local_n_heads = n_heads // tp_size
self.local_d_head = d_model // n_heads
# 列并行: QKV 权重按头切分
self.qkv_weight = torch.randn(
3 * self.local_n_heads * self.local_d_head, d_model,
device=f'cuda:{rank}')
# 行并行: 输出投影按行切分
self.o_weight = torch.randn(
d_model, self.local_n_heads * self.local_d_head,
device=f'cuda:{rank}')
def forward(self, x):
"""前向: 各卡算部分头, AllReduce 汇总"""
# 1. 各卡算自己的 n_heads/tp_size 个头
qkv = torch.matmul(x, self.qkv_weight.T)
q, k, v = qkv.split(self.local_n_heads * self.local_d_head, dim=-1)
# 2. 本地 attention
attn = self._attention(q, k, v)
# 3. 行并行输出投影
out = torch.matmul(attn, self.o_weight.T)
# 4. AllReduce 汇总各卡结果
dist.all_reduce(out, op=dist.ReduceOp.SUM)
return out
def _attention(self, q, k, v):
# 标准 scaled dot-product attention
scores = torch.matmul(q, k.transpose(-1, -2)) / (self.local_d_head ** 0.5)
return torch.matmul(torch.softmax(scores, dim=-1), v)
# 量化: LLaMA-2-70B FP16 需 140GB, 单卡不可行
# TP=4 (A100 80GB): 每卡 35GB 权重 + KV Cache, 可行
# TP 通信开销: AllReduce 每 layer 2 次, 4卡延迟增 15%
# TP=8 时延迟增 35%, 收益递减 (通信占比升高)
python
# 来源:流水并行实现 / DeepSpeed 0.14
class PipelineParallelRunner:
"""流水并行: 层切分到多卡, micro-batch 流水"""
def __init__(self, model_layers, pp_size, rank):
self.pp_size = pp_size
self.rank = rank
# 每卡负责一部分层
layers_per_stage = len(model_layers) // pp_size
start = rank * layers_per_stage
self.layers = model_layers[start:start + layers_per_stage]
self.is_first = rank == 0
self.is_last = rank == pp_size - 1
def forward(self, micro_batches):
"""1F1B 流水调度: 1 Forward 1 Backward 交替"""
# 暖身: 先做 pp_size-1 个 forward 填满流水
in_flight = []
for i in range(min(self.pp_size - self.rank, len(micro_batches))):
mb = micro_batches[i]
if not self.is_first:
mb = self._recv_from_prev()
mb = self._forward_stage(mb)
if not self.is_last:
self._send_to_next(mb)
in_flight.append(mb)
# 稳态: 1F1B 交替
for i in range(self.pp_size - self.rank, len(micro_batches)):
# Forward
mb = micro_batches[i]
if not self.is_first:
mb = self._recv_from_prev()
mb = self._forward_stage(mb)
if not self.is_last:
self._send_to_next(mb)
# Backward (来自下一 stage)
if not self.is_last:
grad = self._recv_grad_from_next()
# ... backward 略
def _forward_stage(self, mb):
for layer in self.layers:
mb = layer(mb)
return mb
# 量化: PP=4 时流水气泡占 25% (空等)
# micro-batch 数越多气泡占比越低: m=4 气泡25%, m=16 气泡6%
# PP 通信少 (仅传激活), 但延迟 = stage数 * 单stage延迟
# 适合: 大模型低延迟不敏感, 高吞吐场景
量化:LLaMA-2-70B FP16 需 140GB,TP=4 每卡 35GB 可行,4 卡延迟增 15%,8 卡增 35%(收益递减)。PP=4 流水气泡 25%,micro-batch=16 降至 6%。TP+PP 混合(TP=4 PP=2)是 70B 常用配置,平衡通信与气泡。
边界:TP 的 AllReduce 通信随卡数增长------超过 8 卡通信开销超计算收益。PP 的流水气泡无法消除------需 1F1B 调度+大 micro-batch 数最小化。MoE 模型需专家并行(EP)------All-to-All 通信是瓶颈,需 InfiniBand 高带宽。跨机通信延迟是单机内 10 倍------TP 限机内(8 卡),PP 用跨机。
6. 推理服务架构:负载均衡与弹性伸缩
推理服务需处理流量波动、长尾延迟、故障恢复。核心组件:负载均衡器、请求队列、自动伸缩、健康检查。架构设计决定 SLA 保障能力。
#mermaid-svg-WS3ikX4EofXoUsF8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WS3ikX4EofXoUsF8 .error-icon{fill:#552222;}#mermaid-svg-WS3ikX4EofXoUsF8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WS3ikX4EofXoUsF8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WS3ikX4EofXoUsF8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WS3ikX4EofXoUsF8 .marker.cross{stroke:#333333;}#mermaid-svg-WS3ikX4EofXoUsF8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WS3ikX4EofXoUsF8 p{margin:0;}#mermaid-svg-WS3ikX4EofXoUsF8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster-label text{fill:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster-label span{color:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster-label span p{background-color:transparent;}#mermaid-svg-WS3ikX4EofXoUsF8 .label text,#mermaid-svg-WS3ikX4EofXoUsF8 span{fill:#333;color:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 .node rect,#mermaid-svg-WS3ikX4EofXoUsF8 .node circle,#mermaid-svg-WS3ikX4EofXoUsF8 .node ellipse,#mermaid-svg-WS3ikX4EofXoUsF8 .node polygon,#mermaid-svg-WS3ikX4EofXoUsF8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WS3ikX4EofXoUsF8 .rough-node .label text,#mermaid-svg-WS3ikX4EofXoUsF8 .node .label text,#mermaid-svg-WS3ikX4EofXoUsF8 .image-shape .label,#mermaid-svg-WS3ikX4EofXoUsF8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-WS3ikX4EofXoUsF8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WS3ikX4EofXoUsF8 .rough-node .label,#mermaid-svg-WS3ikX4EofXoUsF8 .node .label,#mermaid-svg-WS3ikX4EofXoUsF8 .image-shape .label,#mermaid-svg-WS3ikX4EofXoUsF8 .icon-shape .label{text-align:center;}#mermaid-svg-WS3ikX4EofXoUsF8 .node.clickable{cursor:pointer;}#mermaid-svg-WS3ikX4EofXoUsF8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WS3ikX4EofXoUsF8 .arrowheadPath{fill:#333333;}#mermaid-svg-WS3ikX4EofXoUsF8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WS3ikX4EofXoUsF8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WS3ikX4EofXoUsF8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WS3ikX4EofXoUsF8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WS3ikX4EofXoUsF8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WS3ikX4EofXoUsF8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster text{fill:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 .cluster span{color:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WS3ikX4EofXoUsF8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WS3ikX4EofXoUsF8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-WS3ikX4EofXoUsF8 .icon-shape,#mermaid-svg-WS3ikX4EofXoUsF8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WS3ikX4EofXoUsF8 .icon-shape p,#mermaid-svg-WS3ikX4EofXoUsF8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WS3ikX4EofXoUsF8 .icon-shape .label rect,#mermaid-svg-WS3ikX4EofXoUsF8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WS3ikX4EofXoUsF8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WS3ikX4EofXoUsF8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WS3ikX4EofXoUsF8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-WS3ikX4EofXoUsF8 .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-WS3ikX4EofXoUsF8 .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-WS3ikX4EofXoUsF8 .default tspan{fill:#000000!important;} 客户端
负载均衡: Nginx/Envoy
推理服务集群
GPU节点1
GPU节点2
GPU节点N
请求队列
Continuous Batching
监控指标
自动伸缩
python
# 来源:推理服务架构 / 生产实践 2024
import time
from collections import deque
class InferenceLoadBalancer:
"""推理服务负载均衡器"""
def __init__(self, backends, strategy='least_latency'):
self.backends = backends # [{'url', 'healthy', 'load', 'p99'}]
self.strategy = strategy
def route(self, request):
"""路由请求到最优后端"""
healthy = [b for b in self.backends if b['healthy']]
if not healthy:
raise Exception('无可用后端')
if self.strategy == 'least_latency':
# 选 P99 最低的后端
backend = min(healthy, key=lambda b: b['p99'])
elif self.strategy == 'least_load':
# 选负载最低
backend = min(healthy, key=lambda b: b['load'])
elif self.strategy == 'prefix_aware':
# 前缀感知: 同前缀路由到同节点 (命中Prefix Cache)
prefix_hash = self._hash_prefix(request['prompt'])
backend = self._find_cached(prefix_hash) or healthy[0]
return backend
def _hash_prefix(self, prompt):
import hashlib
return hashlib.md5(prompt[:100].encode()).hexdigest()
def health_check(self, interval=5):
"""定期健康检查"""
while True:
for b in self.backends:
try:
latency = self._ping(b['url'])
b['healthy'] = latency < 5.0
b['p99'] = latency
except:
b['healthy'] = False
time.sleep(interval)
def _ping(self, url):
return 0.08 # 占位
# 量化: prefix_aware 路由使 Prefix Cache 命中率 40% -> 85%
# 对比轮询: 首token延迟降 60%
python
# 来源:自动伸缩策略 / 生产实践 2024
class AutoScaler:
"""推理服务自动伸缩器"""
def __init__(self, min_replicas=2, max_replicas=10,
scale_up_qps=80, scale_down_qps=20):
self.min = min_replicas
self.max = max_replicas
self.up_threshold = scale_up_qps
self.down_threshold = scale_down_qps
self.current = min_replicas
def evaluate(self, current_qps, current_p99, p99_threshold=500):
"""评估是否伸缩"""
# 扩容条件: QPS超阈值 或 P99超SLA
if current_qps > self.up_threshold or current_p99 > p99_threshold:
target = min(self.current + 1, self.max)
# 缩容条件: QPS低且P99正常
elif current_qps < self.down_threshold and current_p99 < p99_threshold * 0.5:
target = max(self.current - 1, self.min)
else:
target = self.current
if target != self.current:
self._scale(target)
self.current = target
def _scale(self, n):
# 实际调用 K8s API 或云厂商 SDK
print(f'伸缩到 {n} 副本')
# 量化: 自动伸缩使资源利用率从 30% 升至 70%
# P99 SLA 违规率从 5% 降至 0.1%
# GPU 成本降 40% (低峰自动缩容)
量化:prefix_aware 路由使 Prefix Cache 命中率从 40% 升至 85%,首 token 延迟降 60%。自动伸缩使资源利用率从 30% 升至 70%,P99 SLA 违规率从 5% 降至 0.1%,GPU 成本降 40%。伸缩阈值需配合预热------GPU 启动+模型加载需 30-60 秒,扩容需提前 1 分钟预警。
边界:推理服务扩容慢------GPU 节点启动+模型加载 30-60 秒,无法应对突发流量,需预留 buffer。负载均衡的 prefix_aware 策略需节点亲和性------节点故障致缓存失效。多模型混部时 GPU 切换开销大------模型切换需重加载权重,宜单模型独占节点。
7. 边界与失败模式
推理引擎选型与运维失败模式集中在架构不匹配、显存溢出、延迟尖峰三类。
#mermaid-svg-28KW9WCgsoYupSC0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-28KW9WCgsoYupSC0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-28KW9WCgsoYupSC0 .error-icon{fill:#552222;}#mermaid-svg-28KW9WCgsoYupSC0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-28KW9WCgsoYupSC0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-28KW9WCgsoYupSC0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-28KW9WCgsoYupSC0 .marker.cross{stroke:#333333;}#mermaid-svg-28KW9WCgsoYupSC0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-28KW9WCgsoYupSC0 p{margin:0;}#mermaid-svg-28KW9WCgsoYupSC0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-28KW9WCgsoYupSC0 .cluster-label text{fill:#333;}#mermaid-svg-28KW9WCgsoYupSC0 .cluster-label span{color:#333;}#mermaid-svg-28KW9WCgsoYupSC0 .cluster-label span p{background-color:transparent;}#mermaid-svg-28KW9WCgsoYupSC0 .label text,#mermaid-svg-28KW9WCgsoYupSC0 span{fill:#333;color:#333;}#mermaid-svg-28KW9WCgsoYupSC0 .node rect,#mermaid-svg-28KW9WCgsoYupSC0 .node circle,#mermaid-svg-28KW9WCgsoYupSC0 .node ellipse,#mermaid-svg-28KW9WCgsoYupSC0 .node polygon,#mermaid-svg-28KW9WCgsoYupSC0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-28KW9WCgsoYupSC0 .rough-node .label text,#mermaid-svg-28KW9WCgsoYupSC0 .node .label text,#mermaid-svg-28KW9WCgsoYupSC0 .image-shape .label,#mermaid-svg-28KW9WCgsoYupSC0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-28KW9WCgsoYupSC0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-28KW9WCgsoYupSC0 .rough-node .label,#mermaid-svg-28KW9WCgsoYupSC0 .node .label,#mermaid-svg-28KW9WCgsoYupSC0 .image-shape .label,#mermaid-svg-28KW9WCgsoYupSC0 .icon-shape .label{text-align:center;}#mermaid-svg-28KW9WCgsoYupSC0 .node.clickable{cursor:pointer;}#mermaid-svg-28KW9WCgsoYupSC0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-28KW9WCgsoYupSC0 .arrowheadPath{fill:#333333;}#mermaid-svg-28KW9WCgsoYupSC0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-28KW9WCgsoYupSC0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-28KW9WCgsoYupSC0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-28KW9WCgsoYupSC0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-28KW9WCgsoYupSC0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-28KW9WCgsoYupSC0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-28KW9WCgsoYupSC0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-28KW9WCgsoYupSC0 .cluster text{fill:#333;}#mermaid-svg-28KW9WCgsoYupSC0 .cluster span{color:#333;}#mermaid-svg-28KW9WCgsoYupSC0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-28KW9WCgsoYupSC0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-28KW9WCgsoYupSC0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-28KW9WCgsoYupSC0 .icon-shape,#mermaid-svg-28KW9WCgsoYupSC0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-28KW9WCgsoYupSC0 .icon-shape p,#mermaid-svg-28KW9WCgsoYupSC0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-28KW9WCgsoYupSC0 .icon-shape .label rect,#mermaid-svg-28KW9WCgsoYupSC0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-28KW9WCgsoYupSC0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-28KW9WCgsoYupSC0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-28KW9WCgsoYupSC0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-28KW9WCgsoYupSC0 .default>*{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-28KW9WCgsoYupSC0 .default span{fill:#faf9f5!important;stroke:#ffffff!important;color:#000000!important;stroke-width:0px!important;}#mermaid-svg-28KW9WCgsoYupSC0 .default tspan{fill:#000000!important;} 引擎失败模式
架构不匹配
显存溢出 OOM
延迟尖峰
新模型无KV Cache接口
MoE模型支持不全
KV Cache超预估
batch设置过高
Prefill阻塞Decode
GC/内存整理卡顿
等社区适配或自定义
PagedAttention+量化
Chunked Prefill
python
# 来源:引擎健康监控 / 生产实践 2024
class EngineHealthMonitor:
"""推理引擎健康监控"""
def __init__(self, engine):
self.engine = engine
self.metrics = {'qps': [], 'p99': [], 'gpu_mem': [], 'gpu_util': []}
def monitor(self, interval=1.0):
"""持续监控"""
while True:
self.metrics['qps'].append(self._measure_qps())
self.metrics['p99'].append(self._measure_p99())
self.metrics['gpu_mem'].append(self._gpu_memory())
self.metrics['gpu_util'].append(self._gpu_util())
self._alert_if_abnormal()
time.sleep(interval)
def _alert_if_abnormal(self):
# P99 突增告警
if self.metrics['p99'][-1] > self.metrics['p99'][-10]*2:
self._alert('P99延迟突增, 可能Prefill阻塞')
# 显存接近上限
if self.metrics['gpu_mem'][-1] > 0.95:
self._alert('GPU显存95%, 可能OOM, 降batch')
# GPU利用率骤降
if self.metrics['gpu_util'][-1] < 0.3:
self._alert('GPU利用率<30%, 检查请求队列')
def _measure_qps(self):
return 100 # 占位
def _measure_p99(self):
return 80 # 占位
def _gpu_memory(self):
return 0.7
def _gpu_util(self):
return 0.85
def _alert(self, msg):
print(f'[ALERT] {msg}')
import time
# 量化: 监控使 OOM 事故率降 90%
# 提前 30 秒预警显存压力, 自动降 batch 避免崩溃
实战复盘:某 70B 模型服务用 vLLM 部署,上线后频繁 OOM 崩溃。诊断发现 KV Cache 显存预估未考虑长序列请求------偶发 8K 请求使 batch 内其他请求 KV Cache 超限。引入 PagedAttention 动态分配+显存预占 80% 上限,OOM 归零。教训:长序列场景必须动态 KV Cache 管理,静态预分配必崩。
实战复盘:某实时对话服务用 TensorRT-LLM,模型迭代后忘重编译引擎,线上仍跑旧模型 2 周未发现。引入引擎版本校验------模型 hash 与引擎 hash 绑定,不匹配拒绝启动。教训:TensorRT-LLM 编译流程必须纳入 CI/CD,模型变更自动触发重编译。
总结
推理引擎核心在于 vLLM、SGLang、TensorRT-LLM、llama.cpp 四点。vLLM 靠 PagedAttention+Continuous Batching 实现高吞吐(6000 tokens/s),是通用在线服务首选。SGLang 靠 RadixAttention+约束解码优化多轮对话与 Agent 场景,延迟降 40%。TensorRT-LLM 靠定制 kernel 实现极致延迟(P50 40ms),适合实时场景但需离线编译。llama.cpp 靠 GGUF 量化实现边缘部署,7B 模型 4GB 可跑。选型决策:高并发在线选 vLLM,多轮 Agent 选 SGLang,实时低延迟选 TensorRT-LLM,边缘离线选 llama.cpp。