LLM服务框架

LLM服务框架对比2026:高性能推理引擎之争

引言 LLM服务框架决定了模型的推理速度、资源利用率和最终的服务成本。2026年,vLLM、TGI、TensorRT-LLM等框架在性能上你追我赶。本文将通过系统化测试,帮你选择最佳的LLM服务框架。 参评框架 框架 厂商 版本 特点 vLLM UC Berkeley 0.8 PagedAttention,通用性强 TGI HuggingFace 3.0 生态丰富,易用 TensorRT-LLM NVIDIA 0.15 NVIDIA官方,性能极致 llama.cpp 开源 b3500 CPU/GPU通用,轻量 MLServer Seldon 1.5 企业级,多协议 Ollama Ollama 0.5 最易用,生态好 LMDeploy 上海AI Lab 0.5 国产优化,全流程 性能基准 吞吐量(tokens/s) 在A100 80GB上运行GLM-5 32B: 框架 FP16 INT8 INT4 并发32 vLLM 285 380 520 3500 TGI 210 290 410 2800 TensorRT-LLM 320 430 580 4200 llama.cpp 85 150 210 - LMDeploy 270 365 500 3200 延迟 单请求延迟(P95): ...

2026-07-02 · 3 min · 447 words · 硅基 AGI 探索者
AI推理加速技术2026:量化、剪枝、蒸馏全景

AI推理加速技术2026:量化、剪枝、蒸馏全景

大模型的训练成本固然惊人,但2026年行业共识是:推理成本才是决定AI商业成败的关键。每Token推理成本直接决定了AI应用的经济模型——当GPT-5的推理成本降低10倍,它能打开的市场空间会增加100倍。本文将深度解析2026年最主流的推理加速技术。 一、为什么推理优化如此重要 成本结构的变化 AI推理成本在2026年发生了根本性变化: 发展阶段 成本焦点 核心问题 2020-2022 训练成本 能否训练得起大模型 2023-2024 推理成本 能否部署得起大模型 2025-2026 效率优化 如何以更低成本服务更多用户 2026年,全球AI推理日均Token消耗量突破10万亿,推理基础设施成本超过2000亿美元/年。每降低1%的推理成本,意味着每年节省20亿美元。 延迟 vs 吞吐 vs 成本 推理优化有三个核心目标,它们之间存在权衡: 延迟(Latency):单个请求的响应时间(TTFT, Time to First Token) 吞吐(Throughput):单位时间内处理的请求数(tokens/s) 成本(Cost):每个Token的推理成本 Batch size大 → 吞吐高、延迟高、成本低 Batch size小 → 吞吐低、延迟低、成本高 实际优化需要根据场景选择优先级: 在线服务(Chat):延迟优先 离线批处理:吞吐优先 大规模部署:成本优先 二、量化(Quantization):精度换速度 量化原理 量化是将模型参数从高精度(FP32/FP16)转换为低精度(INT8/INT4/FP8)的过程。理论上: FP32 → FP16:精度损失极小,速度×2,显存÷2 FP16 → INT8:速度×2-4,显存÷4,精度损失<1%(通常) INT8 → INT4:速度×4-8,显存÷8,精度损失5-15%(可优化) 2026年主流量化方法对比 方法 精度 速度 显存节省 质量损失 适用场景 FP16(基准) 100% 1× 1× 0% 通用 FP8(E4M3/E5M2) 99.5% 1.3× 1.5× <0.5% Hopper/Blackwell INT8(对称) 98-99% 1.8× 2× 1-2% 通用 INT8(非对称) 98-99% 1.6× 2× 1-2% 激活分布不均 INT4(GPTQ) 95-97% 3.5× 4× 3-5% 显存受限 INT4(AWQ) 96-98% 3.2× 4× 2-4% 显存受限 INT4(llama.cpp GGUF) 94-97% 4× 4× 3-6% 本地部署 NF4(BitsAndBytes) 95-97% 2.5× 4× 3-5% QLoRA微调 量化方法深度解析 1. Post-Training Quantization (PTQ) 训练后量化是最简单的方式——先训练好模型,再量化。2026年主流PTQ方法: ...

2026-06-30 · 3 min · 542 words · 硅基 AGI 探索者
ai inference serving

AI 推理服务架构:从单机到分布式弹性扩展

1. 推理服务的核心挑战 模型训练完成后,推理服务是将模型价值交付给用户的关键环节。与训练不同,推理服务面临独特挑战: 延迟敏感:用户期望秒级甚至毫秒级响应 吞吐与延迟权衡:批处理提高吞吐但增加单请求延迟 GPU 资源昂贵:需最大化利用率 弹性需求:流量峰谷差异可达 10 倍以上 多模型管理:同时服务数十个模型版本 2. 架构演进路线 阶段1: 单机单GPU 阶段2: 单机多GPU 阶段3: 分布式集群 ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ FastAPI │ │ FastAPI │ │ API Gateway │ │ + HF Model │ → │ + vLLM │ → │ + vLLM Cluster │ │ + 1 GPU │ │ + 4 GPUs │ │ + K8s Autoscale │ └──────────────┘ └──────────────┘ └──────────────────┘ 延迟: 500ms 延迟: 200ms 延迟: 150ms QPS: 5 QPS: 80 QPS: 1000+ 3. 推理引擎选型 3.1 引擎对比 引擎 优势 劣势 适用场景 vLLM PagedAttention,高吞吐 仅支持主流模型 LLM 生产服务 TensorRT-LLM 极致优化,NVIDIA 官方 编译复杂,灵活性低 极致性能场景 TGI HF 官方,生态好 性能略逊 vLLM HF 模型服务 Ollama 部署简单 性能一般 本地/开发环境 SGLang 结构化生成优化 生态较新 结构化输出 3.2 vLLM 部署 # vLLM 服务启动配置 VLLM_CONFIG = { "model": "meta-llama/Llama-3-70B", "tensor_parallel_size": 4, # 4 GPU 张量并行 "gpu_memory_utilization": 0.90, # GPU 内存利用率 "max_model_len": 8192, # 最大上下文长度 "max_num_seqs": 256, # 最大并发序列 "swap_space": 16, # CPU 交换空间 (GB) "enable_prefix_caching": True, # 前缀缓存 "enable_chunked_prefill": True, # 分块预填充 "enforce_eager": False, # 使用 CUDA Graph "dtype": "float16", # 精度 "quantization": "awq", # 量化 "served_model_name": "llama-3-70b", # 对外模型名 } # 启动命令 # python -m vllm.entrypoints.openai.api_server --config config.json 3.3 TensorRT-LLM 优化 import tensorrt as trt import tensorrt_llm from tensorrt_llm.runtime import ModelRunner, GenerationSession class TensorRTEngine: """ TensorRT-LLM 推理引擎 构建 → 序列化 → 反序列化 → 推理 """ def __init__(self, model_dir: str, engine_dir: str): self.model_dir = model_dir self.engine_dir = engine_dir self.runner: ModelRunner = None def build_engine(self, config: dict): """构建 TensorRT 引擎(一次性操作)""" builder = tensorrt_llm.Builder() builder_config = builder.create_builder_config( name="llama", precision=config.get("precision", "fp16"), tensor_parallel_size=config.get("tp_size", 1), pipeline_parallel_size=config.get("pp_size", 1), max_batch_size=config.get("max_batch_size", 256), max_input_len=config.get("max_input_len", 2048), max_output_len=config.get("max_output_len", 512), max_beam_width=config.get("max_beam_width", 1), use_gpt_attention=config.get("use_gpt_attention", True), use_plugin=True, ) # 构建并序列化引擎 engine = builder.build_model(builder_config, self.model_dir) engine.serialize(self.engine_dir) def load_engine(self): """加载已构建的引擎""" self.runner = ModelRunner.from_dir( self.engine_dir, rank=0, is_pp_first=True, is_pp_last=True ) async def generate(self, prompt_ids: list[int], max_new_tokens: int = 256) -> list[int]: session = GenerationSession( model_config=self.runner.model_config, engine=self.runner.engine, input_ids=prompt_ids ) session.decode(max_new_tokens=max_new_tokens) return session.output_ids 4. 批处理与调度 4.1 动态批处理 import asyncio from dataclasses import dataclass, field from collections import deque import time @dataclass class InferenceRequest: request_id: str input_ids: list[int] max_tokens: int temperature: float = 1.0 top_p: float = 0.9 stream: bool = False arrival_time: float = field(default_factory=time.time) future: asyncio.Future = field(default_factory=asyncio.get_event_loop().create_future) class DynamicBatcher: """ 动态批处理器:收集请求到批次中,达到阈值或超时后提交 核心:在延迟和吞吐之间权衡 """ def __init__(self, engine, max_batch_size: int = 32, max_wait_ms: float = 50, max_seq_len: int = 2048): self.engine = engine self.max_batch_size = max_batch_size self.max_wait_ms = max_wait_ms self.max_seq_len = max_seq_len self.queue: deque[InferenceRequest] = deque() self.running = False async def submit(self, request: InferenceRequest) -> str: self.queue.append(request) return await request.future async def start(self): self.running = True while self.running: batch = await self._collect_batch() if batch: await self._process_batch(batch) async def _collect_batch(self) -> list[InferenceRequest]: batch = [] deadline = time.time() + self.max_wait_ms / 1000 while len(batch) < self.max_batch_size and time.time() < deadline: if self.queue: req = self.queue.popleft() batch.append(req) else: await asyncio.sleep(0.001) return batch async def _process_batch(self, batch: list[InferenceRequest]): # Padding 到相同长度 max_len = min(max(len(r.input_ids) for r in batch), self.max_seq_len) padded_inputs = [] attention_masks = [] for req in batch: padding_len = max_len - len(req.input_ids[:max_len]) padded = req.input_ids[:max_len] + [0] * padding_len mask = [1] * min(len(req.input_ids), max_len) + [0] * padding_len padded_inputs.append(padded) attention_masks.append(mask) # 执行批量推理 outputs = await self.engine.generate_batch( input_ids=padded_inputs, attention_mask=attention_masks, max_new_tokens=max(r.max_tokens for r in batch), temperature=max(r.temperature for r in batch), ) # 分发结果 for req, output in zip(batch, outputs): if not req.future.done(): req.future.set_result(output) 4.2 连续批处理(Continuous Batching) class ContinuousBatcher: """ 连续批处理(Iteration-Level Scheduling) 与传统批处理不同:不需要等所有请求完成才接受新请求 每个解码步后都可以加入新请求、移除已完成请求 """ def __init__(self, engine, max_batch_size: int = 256): self.engine = engine self.max_batch_size = max_batch_size self.active_sequences: list[Sequence] = [] self.waiting_queue: deque[Sequence] = deque() @dataclass class Sequence: request_id: str input_ids: list[int] output_ids: list[int] = field(default_factory=list) max_tokens: int = 256 is_finished: bool = False future: asyncio.Future = None async def submit(self, request: InferenceRequest) -> str: seq = self.Sequence( request_id=request.request_id, input_ids=request.input_ids, max_tokens=request.max_tokens, future=asyncio.get_event_loop().create_future() ) self.waiting_queue.append(seq) return await seq.future async def run(self): while True: # 1. 从等待队列添加新序列到活跃批次 while (self.waiting_queue and len(self.active_sequences) < self.max_batch_size): self.active_sequences.append(self.waiting_queue.popleft()) if not self.active_sequences: await asyncio.sleep(0.001) continue # 2. 执行单步解码 step_outputs = await self.engine.step_decode( [s.input_ids + s.output_ids for s in self.active_sequences] ) # 3. 处理输出 finished = [] for seq, output in zip(self.active_sequences, step_outputs): seq.output_ids.append(output.token_id) if output.is_eos or len(seq.output_ids) >= seq.max_tokens: seq.is_finished = True seq.future.set_result(seq.output_ids) finished.append(seq) # 4. 移除已完成序列 self.active_sequences = [s for s in self.active_sequences if not s.is_finished] 5. GPU 资源调度 5.1 多模型 GPU 共享 class GPUScheduler: """GPU 资源调度器:管理多模型在同一 GPU 上的调度""" def __init__(self, gpu_memory_total: int = 80_000): # MB self.total_memory = gpu_memory_total self.allocated: dict[str, int] = {} # model_id -> memory_mb self.model_streams: dict[str, int] = {} # model_id -> cuda_stream def can_load(self, model_memory: int) -> bool: used = sum(self.allocated.values()) return (self.total_memory - used) >= model_memory def allocate(self, model_id: str, memory_mb: int) -> int: if not self.can_load(memory_mb): raise RuntimeError(f"Insufficient GPU memory: need {memory_mb}MB, " f"available {self.total_memory - sum(self.allocated.values())}MB") self.allocated[model_id] = memory_mb return len(self.allocated) # stream id def deallocate(self, model_id: str): self.allocated.pop(model_id, None) self.model_streams.pop(model_id, None) def get_utilization(self) -> float: return sum(self.allocated.values()) / self.total_memory class ModelWarmPool: """模型热池:常用模型常驻 GPU,不常用模型按需加载""" def __init__(self, scheduler: GPUScheduler, storage_path: str): self.scheduler = scheduler self.storage = storage_path self.loaded: dict[str, Any] = {} # model_id -> model instance self.loading_locks: dict[str, asyncio.Lock] = {} self.access_times: dict[str, float] = {} self.idle_threshold = 600 # 10分钟未使用则卸载 async def get_model(self, model_id: str, model_config: dict): if model_id in self.loaded: self.access_times[model_id] = time.time() return self.loaded[model_id] # 防止并发加载同一模型 if model_id not in self.loading_locks: self.loading_locks[model_id] = asyncio.Lock() async with self.loading_locks[model_id]: if model_id in self.loaded: return self.loaded[model_id] # 检查 GPU 内存是否足够 required_mem = model_config["memory_mb"] if not self.scheduler.can_load(required_mem): await self._evict_idle_models(required_mem) # 加载模型 model = await self._load_model(model_id, model_config) self.scheduler.allocate(model_id, required_mem) self.loaded[model_id] = model self.access_times[model_id] = time.time() return model async def _evict_idle_models(self, required_mem: int): """LRU 淘汰空闲模型""" sorted_models = sorted(self.access_times.items(), key=lambda x: x[1]) for model_id, last_access in sorted_models: if time.time() - last_access > self.idle_threshold: await self._unload_model(model_id) if self.scheduler.can_load(required_mem): break async def _unload_model(self, model_id: str): if model_id in self.loaded: del self.loaded[model_id] self.scheduler.deallocate(model_id) self.access_times.pop(model_id, None) import torch torch.cuda.empty_cache() 6. 弹性伸缩 6.1 自动扩缩容控制器 class Autoscaler: """基于指标的自定扩缩容""" def __init__(self, min_replicas: int = 1, max_replicas: int = 10, target_gpu_util: float = 0.7, target_latency_ms: float = 500): self.min_replicas = min_replicas self.max_replicas = max_replicas self.target_gpu_util = target_gpu_util self.target_latency = target_latency_ms self.current_replicas = min_replicas def decide(self, metrics: dict) -> dict: gpu_util = metrics.get("gpu_utilization", 0) avg_latency = metrics.get("avg_latency_ms", 0) queue_depth = metrics.get("queue_depth", 0) qps = metrics.get("qps", 0) # 扩容信号 scale_up_score = 0 if gpu_util > self.target_gpu_util * 1.2: scale_up_score += 2 if avg_latency > self.target_latency * 1.5: scale_up_score += 2 if queue_depth > 50: scale_up_score += 1 # 缩容信号 scale_down_score = 0 if gpu_util < self.target_gpu_util * 0.3: scale_down_score += 2 if avg_latency < self.target_latency * 0.3 and queue_depth < 5: scale_down_score += 1 if qps < 1 and self.current_replicas > 1: scale_down_score += 1 if scale_up_score >= 2 and self.current_replicas < self.max_replicas: return {"action": "scale_up", "replicas": self.current_replicas + 1} elif scale_down_score >= 2 and self.current_replicas > self.min_replicas: return {"action": "scale_down", "replicas": self.current_replicas - 1} else: return {"action": "none", "replicas": self.current_replicas} 6.2 Kubernetes 部署配置 # vllm-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: vllm-llama-70b spec: replicas: 2 selector: matchLabels: app: vllm-llama-70b template: metadata: labels: app: vllm-llama-70b spec: containers: - name: vllm image: vllm/vllm-openai:latest args: - --model=meta-llama/Llama-3-70B - --tensor-parallel-size=4 - --gpu-memory-utilization=0.90 - --max-model-len=8192 resources: limits: nvidia.com/gpu: 4 memory: 128Gi requests: nvidia.com/gpu: 4 memory: 64Gi readinessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 120 periodSeconds: 10 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: vllm-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-llama-70b minReplicas: 2 maxReplicas: 10 metrics: - type: Pods pods: metric: name: gpu_utilization target: type: AverageValue averageValue: "70" - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 7. 负载均衡 class InferenceLoadBalancer: """推理负载均衡器:感知 GPU 负载和模型位置""" def __init__(self): self.backends: dict[str, BackendInfo] = {} @dataclass class BackendInfo: url: str model_id: str gpu_util: float = 0.0 active_requests: int = 0 queue_depth: int = 0 avg_latency_ms: float = 0.0 healthy: bool = True def select(self, model_id: str) -> str: candidates = [ (url, info) for url, info in self.backends.items() if info.model_id == model_id and info.healthy ] if not candidates: raise RuntimeError(f"No healthy backend for model {model_id}") # 最少连接 + 最低延迟加权 def score(info: BackendInfo) -> float: load_score = info.active_requests * 0.5 + info.queue_depth * 0.3 latency_score = info.avg_latency_ms / 1000 * 0.2 return load_score + latency_score return min(candidates, key=lambda x: score(x[1]))[0] def update_health(self, url: str, metrics: dict): if url in self.backends: info = self.backends[url] info.gpu_util = metrics.get("gpu_util", info.gpu_util) info.active_requests = metrics.get("active_requests", info.active_requests) info.avg_latency_ms = metrics.get("avg_latency_ms", info.avg_latency_ms) info.healthy = metrics.get("healthy", True) 8. 性能优化总结 优化手段 吞吐提升 延迟降低 实现复杂度 动态批处理 3-5x -10% ⭐⭐ 连续批处理 5-10x -20% ⭐⭐⭐ TensorRT 优化 2-3x -40% ⭐⭐⭐⭐ 前缀缓存 2x -50% ⭐⭐ AWQ/GPTQ 量化 2x -30% ⭐⭐ Speculative Decoding 1.5x -40% ⭐⭐⭐⭐ 多 GPU 并行 线性 持平 ⭐⭐⭐ 9. 总结 AI 推理服务的架构设计需要平衡延迟、吞吐和成本: ...

2026-06-25 · 7 min · 1424 words · 硅基 AGI 探索者
鲁ICP备2026018361号