推理引擎对比:vLLM / TGI / LMDeploy / SGLang / MLC-LLM 性能基准技术详解是数据治理与合规中的核心主题,属于数据科学与数据工程篇体系。本文系统讲解其基本概念、技术原理和实现方法,涵盖关键算法、工程实践和典型应用场景。适合数据工程师、AI开发者和架构师学习参考,帮助你构建完整的技术知识体系,在实际项目中快速落地应用。

岗位关联

需要学习推理引擎对比:vLLM / TGI / LMDeploy / SGLang / MLC-LLM 性能基准,标注管理本质是数据工程,需理解数据管道和质量控制。本篇涵盖数据清洗/ETL/数据仓库/特征工程,帮助你构建数据管道与洞察。

目录
  1. 可视化演示
  2. 推理引擎核心能力与选型维度
  3. vLLM的PagedAttention与高吞吐优势
  4. TGI与LMDeploy的差异化定位
  5. SGLang的结构化生成与缓存优化
  6. MLC-LLM的跨平台与端侧部署能力
  7. 性能基准测试方法论与场景化选型
  8. AI 应用场景
  9. Python 演示
  10. 常见问答
  11. 常见误区
  12. 参考来源

可视化演示

对比链地址法与开放寻址法处理哈希冲突的过程,实时展示负载因子、冲突次数和链长度的变化。

本节配有交互动效(进入视口后自动加载,约 3KB)。

链地址法 — 冲突用链表解决 相同哈希值的键被组织成链表,插入无需探测,查询需遍历链表 黄色闪烁表示发生冲突,绿色表示正常插入 负载因子 α = 键数 / 表长,α>1 时链表变长

推理引擎核心能力与选型维度

LLM推理引擎的核心能力可以从四个关键维度进行评估:吞吐量(throughput,单位时间内处理的请求数或生成的token数)、延迟(latency,从请求发出到首个token返回及完整响应的时间)、显存效率(memory efficiency,KV Cache管理策略与GPU显存利用率)以及生态成熟度(ecosystem maturity,社区活跃度、模型支持范围、工具链完善程度)。这四个维度往往存在trade-off,高吞吐方案可能牺牲单请求延迟,低延迟方案可能在并发能力上受限。

吞吐量是衡量服务端推理引擎最核心的指标,通常以requests per second (RPS)或tokens per second (TPS)表示。吞吐量取决于多个因素:GPU计算能力、KV Cache管理效率、批处理策略(static batching vs continuous batching)、以及算子优化程度。continuous batching(动态批处理)允许已完成的请求及时退出、新请求随时加入batch,相比static batching显著提高了GPU利用率和吞吐量。

延迟指标需要区分TTFT(Time To First Token,首token延迟)和TPOT(Time Per Output Token,每个输出token的时间)。TTFT主要受prefill阶段计算量和排队时间影响,TPOT主要受decode阶段计算效率影响。不同业务场景对延迟的敏感度不同:实时对话要求TTFT低于500ms,而离线批处理任务可以容忍更高延迟以换取更高吞吐。显存效率决定了单卡能同时服务多少请求,直接影响系统的并发上限和运营成本。

python8 行
# 推理引擎核心评估维度metrics = {    "throughput_rps": "每秒处理请求数",    "ttft_ms": "首token延迟(毫秒)",    "tpot_ms": "每输出token时间(毫秒)",    "gpu_mem_utilization": "GPU显存利用率",    "kv_cache_efficiency": "KV Cache管理效率",}

vLLM的PagedAttention与高吞吐优势

vLLM的核心创新是PagedAttention机制,借鉴操作系统虚拟内存的分页(paging)思想,将KV Cache分割为固定大小的block(通常16个token为一个block),通过block table实现非连续的显存分配。传统推理框架需要为每个请求预分配连续的KV Cache空间,导致严重的显存碎片化和内部碎片(实际使用率通常仅20-40%)。PagedAttention将显存利用率提升到接近90%,使得同一GPU可以同时容纳更多请求的KV Cache,直接提升并发能力和吞吐量。

vLLM的continuous batching(也称为iteration-level scheduling或in-flight batching)在每次decode iteration级别进行调度:已完成的请求立即释放其block,新请求随时插入空闲block。相比传统的request-level batching(等待batch中所有请求都完成才处理下一批),continuous batching大幅减少GPU空闲时间。在请求长度差异较大的实际负载下,continuous batching相比static batching可提升2-4倍吞吐量。

vLLM拥有当前最活跃的开源推理引擎社区,支持数百种模型架构(包括Llama、Mistral、Qwen、ChatGLM等),与HuggingFace Transformers深度集成,支持多种量化格式(AWQ、GPTQ、FP8)。其Pythonic API设计降低了使用门槛,Tensor Parallelism支持多卡推理。vLLM在高吞吐服务端推理场景中通常是首选方案,尤其适合请求量大、模型多样的生产环境。

python6 行
# vLLM PagedAttention核心思想# KV Cache按block分页管理,非连续分配class PagedKVCache:    block_size = 16  # 每个block存储16个token的KV    # block_table: request_id -> [block_id_0, block_id_1, ...]    # 显存利用率从~30%提升到~90%

TGI与LMDeploy的差异化定位

Text Generation Inference (TGI) 是HuggingFace官方推出的推理服务框架,其最大优势在于与HuggingFace生态的无缝集成:支持所有Transformers模型直接加载,无需模型转换步骤,支持模型自动下载和版本管理。TGI支持continuous batching、PagedAttention(较新版本引入)、多种量化方案(bitsandbytes、GPTQ、AWQ),以及OpenAI兼容的API接口。TGI适合已经深度使用HuggingFace生态的团队,模型迭代和切换成本极低。

LMDeploy由上海人工智能实验室(InternLM团队)开发,其核心引擎TurboMind针对国产GPU(如华为昇腾)和NVIDIA GPU均做了深度优化。TurboMind引入了高效的KV Cache量化(INT8/FP8)、Tensor Parallelism以及类似PagedAttention的显存管理策略。LMDeploy在InternLM系列模型上具有原生优化优势,同时支持W4A16权重量化,在显存受限场景下能部署更大的模型。

TGI与LMDeploy的定位差异明显:TGI走'通用生态'路线,强调模型兼容性和开箱即用;LMDeploy走'深度优化'路线,在特定模型(InternLM系列)和特定硬件(国产GPU)上追求极致性能。在基准测试中,两者在NVIDIA GPU上的吞吐量接近,但LMDeploy在显存优化和量化推理方面可能略有优势,而TGI在模型支持广度和社区资源方面更胜一筹。选择时需权衡生态需求与性能需求。

python6 行
# TGI: HuggingFace生态无缝集成# 启动命令: text-generation-launcher --model-id meta-llama/Llama-3-8B # LMDeploy: TurboMind引擎# 启动命令: lmdeploy serve api_server internlm/internlm2-7b# 支持W4A16量化: lmdeploy lite auto_awq model_path

SGLang的结构化生成与缓存优化

SGLang的核心创新是RadixAttention,基于Radix Tree(基数树/压缩前缀树)数据结构管理所有请求的prefix KV Cache。当多个请求共享相同的前缀(如system prompt、few-shot examples),RadixAttention自动识别并复用已计算的KV Cache,避免重复计算。在多轮对话、Agent调用、共享system prompt等场景中,前缀复用率可达60-80%,显著降低prefill阶段的计算开销和TTFT。

SGLang还提供了强大的结构化生成(structured generation)能力,通过约束解码(constrained decoding)确保模型输出严格遵循指定的JSON Schema、正则表达式或上下文无关文法。这在需要模型输出结构化数据(如函数调用、数据库查询)的场景中至关重要。SGLang的约束解码在Trie树上进行词表掩码(vocabulary masking),相比传统的JSON解码方案(如outlines),性能开销更低且兼容性更好。

在Agent和多轮对话场景中,SGLang的优势尤为明显。Agent工作流通常涉及多次LLM调用,每次调用共享相同的system prompt和工具描述前缀。RadixAttention使得这些公共前缀只需计算一次,后续调用直接复用。多轮对话中,历史轮次的KV Cache也可以被后续轮次复用。SGLang的ReST(Reuse-aware Scheduling with Tree-structured caching)调度算法进一步优化了具有共享前缀的请求的调度顺序,最大化缓存命中率。

python8 行
# SGLang RadixAttention前缀缓存示意# Radix Tree结构:#           root#          /    \#     sys_prompt  sys_prompt_v2#       /    \#   turn_1   turn_2# 共享前缀的KV Cache自动复用,避免重复计算

MLC-LLM的跨平台与端侧部署能力

MLC-LLM(Machine Learning Compilation for LLM)由陈天奇团队开发,基于Apache TVM Unity编译器实现LLM的跨平台部署。与其他推理引擎不同,MLC-LLM采用编译优化(compiler-based optimization)路线:将模型编译为针对目标硬件优化的原生代码,支持NVIDIA GPU、AMD GPU、Apple Silicon (Metal)、Android (OpenCL/Vulkan)、WebGPU等多种后端。这种编译器驱动的方式使得同一套模型可以在从服务器到手机到浏览器的各种设备上运行。

MLC-LLM在端侧部署(edge deployment)方面具有独特优势。通过模型量化(INT4/INT8 weight-only quantization)和编译器级别的算子融合优化,MLC-LLM可以在手机、平板等移动设备上流畅运行7B级别的模型。其WebGPU后端甚至允许在浏览器中直接运行LLM,无需安装任何软件。这对于隐私敏感场景(数据不出设备)、离线场景(无网络连接)和边缘计算场景具有重要价值。

然而,MLC-LLM在服务端高吞吐推理方面存在明显局限。由于采用编译优化路线,每次模型变更或硬件变更都需要重新编译,部署灵活性不如基于Python的推理引擎。MLC-LLM不支持continuous batching和PagedAttention等高级服务端特性,在高并发场景下吞吐量显著低于vLLM和SGLang。因此,MLC-LLM更适合端侧推理和单用户场景,而非高并发服务端部署。

python8 行
# MLC-LLM编译部署流程# 1. 模型编译(针对目标平台)mlc_llm compile model_config.py --target cuda  # NVIDIA GPUmlc_llm compile model_config.py --target metal  # Apple Siliconmlc_llm compile model_config.py --target webgpu  # 浏览器 # 2. 模型转换与量化mlc_llm convert_weight --quantization q4f16_1

性能基准测试方法论与场景化选型

科学的推理引擎基准测试需要控制变量:统一的硬件环境(GPU型号、驱动版本、CUDA版本)、统一的模型(相同参数量、相同精度)、统一的负载模式(请求到达率、输入输出长度分布)。常用基准测试工具包括vLLM的benchmark_serving.py、GenAI-Perf等。测试指标应涵盖吞吐量(RPS/TPS)、延迟分布(P50/P90/P99/TTFT)、显存占用和可扩展性(随并发请求数的性能变化曲线)。

场景化选型是推理引擎选择的核心方法论。不同业务场景对引擎特性的需求差异巨大:高并发在线对话服务需要高吞吐和低TTFT,适合vLLM或SGLang;多轮对话和Agent应用需要高效的前缀缓存,SGLang的RadixAttention是最佳选择;HuggingFace生态深度用户需要快速模型迭代,TGI的开箱即用体验最好;需要部署到国产GPU或特定硬件,LMDeploy的TurboMind是首选;端侧和跨平台部署场景,MLC-LLM是唯一选择。

避免误导性排名是基准测试的重要原则。单纯比较吞吐量排名没有意义,因为不同引擎的设计目标不同。例如,vLLM在高吞吐场景领先但缺乏结构化生成能力,SGLang在前缀缓存场景领先但社区规模较小,MLC-LLM在端侧场景无可替代但服务端性能较弱。正确的选型方法是:明确自身业务场景的核心需求(吞吐优先?延迟优先?前缀复用优先?跨平台优先?),在统一条件下针对该场景进行基准测试,选择在该场景下表现最优的引擎。

python8 行
# 场景化选型决策矩阵selection_matrix = {    "高并发在线对话": {"priority": "throughput+TTFT", "recommended": "vLLM/SGLang"},    "多轮对话/Agent": {"priority": "prefix_cache", "recommended": "SGLang"},    "HF生态快速迭代": {"priority": "compatibility", "recommended": "TGI"},    "国产GPU部署":   {"priority": "hardware_support", "recommended": "LMDeploy"},    "端侧/跨平台":   {"priority": "cross_platform", "recommended": "MLC-LLM"},}

AI 应用场景

高并发对话服务的推理引擎选型与基准测试

阶段:模型部署

解决的问题:解决高并发在线对话服务中推理引擎选择困难的问题,通过统一基准测试和场景化评估确定最优引擎

具体案例:某AI对话平台日均处理500万次对话请求,需要选择推理引擎支撑高并发服务。团队在统一的A100 GPU环境下对vLLM、TGI、SGLang进行基准测试:使用真实业务负载分布(平均输入512 tokens、平均输出256 tokens、泊松到达过程),测量不同并发度下的吞吐量、P99延迟和TTFT。测试发现vLLM在纯吞吐量指标上领先(120 RPS vs TGI 95 RPS vs SGLang 115 RPS),但SGLang在包含共享system prompt的多轮对话场景中因RadixAttention前缀缓存将TTFT降低了40%。最终选择SGLang作为主引擎,因为该平台的对话平均为5轮以上,前缀缓存带来的延迟降低对用户体验的提升远超纯吞吐量的差异。

Python 演示

python177 行
import timeimport randomfrom typing import List, Dict, Tuple, Optionalfrom dataclasses import dataclass, field  @dataclassclass BenchmarkRequest:    """模拟推理请求"""    prompt_tokens: int    max_output_tokens: int    prefix_tokens: int = 0  # 可复用的前缀token数  @dataclassclass EngineResult:    """引擎基准测试结果"""    engine_name: str    throughput_rps: float       # 每秒请求数    avg_latency_ms: float       # 平均延迟(毫秒)    p99_latency_ms: float       # P99延迟    gpu_mem_gb: float           # GPU显存占用    prefix_cache_hit_rate: float  # 前缀缓存命中率  class InferenceEngineSimulator:    """模拟不同推理引擎的性能特征"""     ENGINE_PROFILES = {        "vLLM": {            "base_throughput": 120.0,            "paged_kv_efficiency": 0.92,            "continuous_batching": True,            "prefix_cache": True,            "memory_efficiency": 0.88,        },        "TGI": {            "base_throughput": 95.0,            "paged_kv_efficiency": 0.80,            "continuous_batching": True,            "prefix_cache": False,            "memory_efficiency": 0.78,        },        "LMDeploy": {            "base_throughput": 110.0,            "paged_kv_efficiency": 0.88,            "continuous_batching": True,            "prefix_cache": True,            "memory_efficiency": 0.85,        },        "SGLang": {            "base_throughput": 115.0,            "paged_kv_efficiency": 0.90,            "continuous_batching": True,            "prefix_cache": True,            "radix_attention": True,            "memory_efficiency": 0.87,        },        "MLC-LLM": {            "base_throughput": 45.0,            "paged_kv_efficiency": 0.70,            "continuous_batching": False,            "prefix_cache": False,            "cross_platform": True,            "memory_efficiency": 0.65,        },    }     def __init__(self):        self.results: List[EngineResult] = []     def simulate_benchmark(        self, requests: List[BenchmarkRequest], gpu_mem_total: float = 80.0    ) -> List[EngineResult]:        """对每个引擎运行基准测试模拟"""        for engine_name, profile in self.ENGINE_PROFILES.items():            total_time = 0.0            latencies = []            prefix_hits = 0            mem_used = gpu_mem_total * (1.0 - profile["memory_efficiency"] * 0.3)             for req in requests:                # 计算有效token数(扣除前缀缓存复用)                effective_tokens = req.prompt_tokens                if profile.get("prefix_cache") or profile.get("radix_attention"):                    if req.prefix_tokens > 0:                        reuse = min(req.prefix_tokens, req.prompt_tokens)                        effective_tokens -= int(reuse * profile["paged_kv_efficiency"])                        prefix_hits += 1                 # 模拟处理时间(与有效token数成正比)                process_time = effective_tokens / (profile["base_throughput"] * 0.8)                if profile.get("continuous_batching"):                    process_time *= 0.85  # continuous batching加速                latencies.append(process_time * 1000)                total_time += process_time             # 计算指标            throughput = len(requests) / total_time if total_time > 0 else 0            avg_latency = sum(latencies) / len(latencies) if latencies else 0            sorted_lat = sorted(latencies)            p99_idx = int(len(sorted_lat) * 0.99)            p99_latency = sorted_lat[min(p99_idx, len(sorted_lat) - 1)]            prefix_hit_rate = prefix_hits / len(requests) if requests else 0             result = EngineResult(                engine_name=engine_name,                throughput_rps=round(throughput, 2),                avg_latency_ms=round(avg_latency, 2),                p99_latency_ms=round(p99_latency, 2),                gpu_mem_gb=round(mem_used, 2),                prefix_cache_hit_rate=round(prefix_hit_rate, 3),            )            self.results.append(result)        return self.results  def select_engine(    results: List[EngineResult],    scenario: str = "high_throughput",) -> str:    """根据场景化需求选择最优引擎"""    if scenario == "high_throughput":        best = max(results, key=lambda r: r.throughput_rps)    elif scenario == "low_latency":        best = min(results, key=lambda r: r.p99_latency_ms)    elif scenario == "prefix_heavy":        best = max(results, key=lambda r: r.prefix_cache_hit_rate)    elif scenario == "edge_device":        edge_capable = [r for r in results if r.engine_name == "MLC-LLM"]        best = edge_capable[0] if edge_capable else results[0]    elif scenario == "memory_constrained":        best = min(results, key=lambda r: r.gpu_mem_gb)    else:        best = max(results, key=lambda r: r.throughput_rps)    return best.engine_name  def run_benchmark_comparison():    """运行推理引擎基准对比测试"""    sim = InferenceEngineSimulator()     # 生成混合负载请求    requests = []    for i in range(200):        req = BenchmarkRequest(            prompt_tokens=random.randint(128, 2048),            max_output_tokens=random.randint(64, 512),            prefix_tokens=random.choice([0, 0, 128, 256, 512]),        )        requests.append(req)     print("=" * 60)    print("LLM推理引擎基准对比测试")    print("=" * 60)     results = sim.simulate_benchmark(requests)     print(f"\n{'引擎':<12} {'吞吐(rps)':<12} {'平均延迟(ms)':<14} {'P99延迟(ms)':<14} {'显存(GB)':<10} {'前缀命中率':<10}")    print("-" * 72)    for r in results:        print(f"{r.engine_name:<12} {r.throughput_rps:<12.2f} {r.avg_latency_ms:<14.2f} "              f"{r.p99_latency_ms:<14.2f} {r.gpu_mem_gb:<10.2f} {r.prefix_cache_hit_rate:<10.3f}")     # 场景化选型推荐    scenarios = ["high_throughput", "low_latency", "prefix_heavy", "edge_device", "memory_constrained"]    print(f"\n{'=' * 60}")    print("场景化选型推荐:")    print("-" * 40)    for sc in scenarios:        best = select_engine(results, sc)        print(f"  {sc:<20} -> 推荐引擎: {best}")  if __name__ == "__main__":    random.seed(42)    run_benchmark_comparison()
目的:模拟五大推理引擎(vLLM、TGI、LMDeploy、SGLang、MLC-LLM)的基准对比测试,包含吞吐量/延迟测量、前缀缓存模拟和场景化选型逻辑。
  1. class BenchmarkRequest:定义推理请求数据结构,包含输入token数、最大输出token数和可复用前缀token数
  2. class EngineResult:定义基准测试结果,包含吞吐量、平均延迟、P99延迟、显存占用和前缀缓存命中率
  3. ENGINE_PROFILES = {定义五个引擎的性能特征配置,包括基础吞吐量、KV Cache效率、是否支持continuous batching等
  4. def simulate_benchmark(self, requests, gpu_mem_total):对每个引擎模拟基准测试:遍历请求计算有效token数、处理时间和各项性能指标
  5. effective_tokens = req.prompt_tokens计算有效token数:如果引擎支持前缀缓存,扣除可复用的前缀token
  6. if profile.get('continuous_batching'):支持continuous batching的引擎处理时间乘以0.85加速因子
  7. p99_idx = int(len(sorted_lat) * 0.99)计算P99延迟:将延迟排序后取第99百分位的值
  8. def select_engine(results, scenario):场景化选型函数:根据不同场景(高吞吐/低延迟/前缀密集/端侧/显存受限)选择最优引擎
  9. best = max(results, key=lambda r: r.throughput_rps)高吞吐场景选择吞吐量最高的引擎
  10. best = max(results, key=lambda r: r.prefix_cache_hit_rate)前缀密集场景选择前缀缓存命中率最高的引擎(通常是SGLang)
  11. edge_capable = [r for r in results if r.engine_name == 'MLC-LLM']端侧场景直接选择MLC-LLM,它是唯一支持跨平台端侧部署的引擎
  12. requests.append(req)生成200个混合负载请求,模拟真实场景中输入输出长度和前缀长度的分布
  13. for sc in scenarios:遍历所有场景输出选型推荐,展示场景化选型的核心逻辑
  14. random.seed(42)固定随机种子确保基准测试结果可复现
  15. run_benchmark_comparison()执行完整的基准对比测试流程:生成请求→模拟各引擎→输出结果→场景化推荐

常见问答

vLLM的PagedAttention是如何提升显存利用率的?
PagedAttention将KV Cache分割为固定大小的block(通常16个token),通过block table实现非连续显存分配,类似操作系统虚拟内存的分页机制。传统方案需要预分配连续空间导致仅20-40%利用率,PagedAttention将利用率提升到接近90%,使同一GPU能同时容纳更多请求的KV Cache。
SGLang的RadixAttention相比vLLM的前缀缓存有什么优势?
SGLang的RadixAttention基于Radix Tree数据结构管理所有请求的前缀KV Cache,能自动识别任意请求间的共享前缀(不仅是system prompt,还包括多轮对话历史)。其ReST调度算法优化了具有共享前缀的请求的调度顺序,最大化缓存命中率。在多轮对话和Agent场景中,前缀复用率可达60-80%,显著降低TTFT。
为什么MLC-LLM不适合高并发服务端部署?
MLC-LLM采用编译优化路线,每次模型或硬件变更需重新编译,部署灵活性差。更关键的是,它不支持continuous batching和PagedAttention等高级服务端特性,在高并发场景下吞吐量显著低于vLLM和SGLang。MLC-LLM的设计目标是跨平台端侧部署,而非高吞吐服务端推理。
TGI和LMDeploy的核心定位差异是什么?
TGI走通用生态路线,强调与HuggingFace Transformers的无缝集成和模型兼容性,支持数百种模型直接加载,适合需要快速模型迭代的团队。LMDeploy走深度优化路线,其TurboMind引擎针对国产GPU(华为昇腾)和特定模型(InternLM系列)做了深度优化,支持W4A16量化,在显存受限场景有优势。
为什么不能仅凭吞吐量排名来选择推理引擎?
因为不同引擎的设计目标和优势场景不同。vLLM在高吞吐场景领先但缺乏结构化生成能力,SGLang在前缀缓存和多轮对话场景更优,MLC-LLM在端侧场景无可替代。仅比较吞吐量会忽略延迟、前缀缓存效率、跨平台能力等关键维度。正确的做法是明确业务核心需求,在统一条件下针对该场景进行基准测试。

常见误区

误区基准测试中吞吐量最高的引擎就是最佳选择

正解吞吐量只是众多指标之一,需要综合评估延迟分布(TTFT、P99)、显存效率、前缀缓存命中率、结构化生成能力等多维指标。高吞吐引擎可能在延迟或特定场景适配上不如其他引擎,选型应以业务场景需求为导向进行多指标综合评估

为何常见:吞吐量是最直观易测的指标,容易被当作唯一标准,忽略延迟和场景适配性的重要性

误区vLLM在所有场景都优于其他引擎

正解vLLM在高吞吐服务端推理方面确实领先,但在前缀共享密集的场景SGLang的RadixAttention更优,在端侧跨平台部署场景MLC-LLM是唯一选择,在HuggingFace生态集成深度上TGI更胜一筹,在国产GPU适配上LMDeploy更有优势

为何常见:vLLM社区活跃度高、知名度大,容易形成'最强引擎'的刻板印象,忽略其他引擎在特定场景的差异化优势

误区推理引擎可以即插即用,无需针对业务调优

正解默认配置几乎不可能达到最优性能。需要根据业务特征调整batch size策略、KV Cache block大小、量化精度(INT4/INT8/FP16)、tensor parallelism配置、请求调度参数等。例如前缀密集场景需要启用并优化前缀缓存,长文本场景需要调整block size和显存分配策略

为何常见:推理引擎提供了开箱即用的默认配置,初学者容易认为默认值就是最优值,不了解参数调优对性能的巨大影响

参考来源