跳转至

图模式指南

概述

本指南说明图模式在 vLLM Ascend 中的使用方式。

vLLM 已经提供了通用的图模式架构、模式定义和编译集成。关于这些上游概念,请参见:

本文档聚焦于 Ascend 特定视角:图模式在 Ascend 上如何工作、涉及哪些组件、如何配置它们,以及用户需要注意哪些约束。

Ascend 上的当前状态

  • 图模式目前同时支持 Model Runner V1/V2。
  • ACLGraph(通过 torch.npu.NPUGraph 进行捕获/重放)是 Ascend 上默认图路径使用的运行时图执行机制。
  • Npugraph_ex 是一个编译时 FX 图优化层,在 FULL/FULL_DECODE_ONLY 模式下默认启用。它会在 ACLGraph 捕获该图之前优化该图。
  • XliteGraph 是面向特定模型系列和环境的可选图路径。
  • 在上下文并行场景中,cudagraph_mode="FULL" 尚未得到充分支持。

Ascend 上的图路径

vLLM Ascend 提供两种图路径:

图路径 默认 描述 起始版本
ACLGraph (+ Npugraph_ex) 是 编译时 FX 优化(Npugraph_ex)+ 运行时捕获/重放(ACLGraph) v0.9.0rc1(Npugraph_ex 自 v0.15.0rc1 起)
XliteGraph 否 面向特定模型系列的预配置图路径。需要单独安装 v0.11.0

图模式在 Ascend 上的工作原理

Ascend 上的默认图路径包含两个阶段:编译时优化和运行时捕获/重放。ACLGraph 负责运行时捕获/重放。编译时阶段因 cudagraph_mode 而异:

  • FULL_AND_PIECEWISE:默认模式,与上游 vLLM 策略相同。编译时路径遵循 PIECEWISE 编译,而运行时对于均匀解码批次仍可能使用完整图行为。
  • FULL / FULL_DECODE_ONLY:Npugraph_ex 通过 npugraph_ex 优化 FX 图(force_eager=True,仅编译时,不进行捕获)。优化后的可调用对象随后在运行时由 ACLGraph 捕获并重放。
  • PIECEWISE:Npugraph_ex 被禁用。编译时仅应用基本的 FX 融合传递。ACLGraph 在运行时捕获并重放生成的可调用对象。
  • NONE:不进行编译或图捕获。模型以急切模式运行。
cudagraph_mode 编译时 运行时 Npugraph_ex
FULL_AND_PIECEWISE 分段编译路径 混合:混合批次使用 PIECEWISE,均匀解码批次支持 FULL 禁用
FULL / FULL_DECODE_ONLY Npugraph_ex FX 优化 ACLGraph 捕获/重放 启用
PIECEWISE 仅融合传递 ACLGraph 捕获/重放 禁用
NONE 无 急切执行 禁用

Ascend 设置 use_inductor=False,并选择其自身的编译后端。该后端会根据配置应用 npugraph_ex 优化或 FX 融合传递。

此外,XliteGraph 可作为面向特定模型系列的可选替代图路径(参见 使用 XliteGraph)。

使用 ACLGraph

ACLGraph 是 Ascend 上的运行时图捕获/重放机制。当图模式处于活动状态(即 cudagraph_mode 不为 NONE)时,它会自动启用,并且不需要显式配置。

基本用法

离线示例:

from vllm import LLM

llm = LLM(model="path/to/Qwen3-0.6B")
outputs = llm.generate("Hello, how are you?")

在线示例:

vllm serve Qwen/Qwen3-0.6B

显式 cudagraph_mode 配置

通用的 cudagraph_mode 选项来自上游 vLLM。在 Ascend 上,最终生效的模式仍可能根据平台和后端支持情况进行调整,因此官方 vLLM CUDA Graphs 文档仍是模式语义的权威参考。

CLI 示例:

vllm serve Qwen/Qwen3-0.6B \
  --compilation-config '{"cudagraph_mode": "PIECEWISE"}'

Python 示例:

from vllm import LLM

llm = LLM(
    model="Qwen/Qwen3-0.6B",
    compilation_config={"cudagraph_mode": "PIECEWISE"},
)

关于 NONE、PIECEWISE、FULL、FULL_DECODE_ONLY 和 FULL_AND_PIECEWISE 的详细含义,以及通用回退策略,请参见上游 CUDA Graphs 设计文档。

注意力后端兼容性

并非所有注意力后端都支持所有图模式。vLLM 会在兼容性检查期间检查注意力后端兼容性,并在可能时自动将 cudagraph_mode 调整为更兼容的模式,而不是立即失败。实际上,这意味着请求的完整图模式可能会被缩小为混合模式或分段模式;如果后端完全无法支持图执行,则图模式可能会被禁用。

在 Ascend 上,当前注意力后端的支持级别如下:

注意力后端 声明支持 实际含义
attention_v1 ALWAYS 支持混合预填充/解码批次的图执行
context_parallel/attention_cp ALWAYS 支持混合预填充/解码批次的图执行
mla_v1 UNIFORM_BATCH 图执行仅限于均匀批次;完整图限制更多
context_parallel/mla_cp UNIFORM_BATCH 图执行仅限于均匀批次;完整图限制更多
sfa_v1 UNIFORM_BATCH 图执行仅限于均匀批次;完整图限制更多
context_parallel/sfa_cp UNIFORM_BATCH 图执行仅限于均匀批次;完整图限制更多

这就是为什么 Ascend 上实际生效的图模式可能与配置中请求的模式不同。

排查捕获资源耗尽

如果由于配置的图大小超过当前栈上可用的运行时资源,导致 ACLGraph 捕获失败,vLLM Ascend 现在会抛出带有缓解指导的专用错误。实际上,最有用的操作是:

  • 如果可用,请升级到更新的 HDK/CANN 软件栈;
  • 降低 cudagraph_capture_sizes 或 max_cudagraph_capture_size;
  • 当工作负载主要为统一解码时,优先使用 FULL 或 FULL_DECODE_ONLY;
  • 临时禁用图模式,以确认问题与捕获相关。

这最有可能出现在 PIECEWISE 或 FULL_AND_PIECEWISE 配置中,因为这些路径相比统一全图解码往往会捕获更多图。

使用 Npugraph_ex

如 RFC 中所述,Npugraph_ex 是一个编译期 FX 图优化层,它与 ACLGraph 协同工作。它会在 ACLGraph 于运行时捕获之前优化模型的 FX 图。其性能收益主要来自将多个算子融合为单个内核(例如,add + rms_norm → npu_add_rms_norm),从而降低内核启动开销。

Atlas 300I DUO

Atlas 300I DUO 和 Atlas 200I Pro 不支持 enable_npugraph_ex。请设置 --additional-config '{"ascend_compilation_config": {"enable_npugraph_ex":false}}'.

默认行为

在支持的硬件上,当 cudagraph_mode 为 FULL 或 FULL_DECODE_ONLY 时,Npugraph_ex 默认启用。在 FULL_AND_PIECEWISE、PIECEWISE 和 NONE 模式下会自动禁用。

选择全图模式以使用此默认设置:

from vllm import LLM

# Npugraph_ex is enabled by default in FULL/FULL_DECODE_ONLY mode
llm = LLM(model="path/to/Qwen2-7B-Instruct", compilation_config={"cudagraph_mode": "FULL_DECODE_ONLY"})
outputs = llm.generate("Hello, how are you?")

显式配置

要显式控制 Npugraph_ex:

离线示例:

from vllm import LLM

model = LLM(
    model="path/to/Qwen2-7B-Instruct",
    additional_config={
        "ascend_compilation_config": {
            "enable_npugraph_ex": True,
        }
    }
)
outputs = model.generate("Hello, how are you?")

在线示例:

vllm serve Qwen/Qwen2-7B-Instruct \
  --additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":true}}'

要显式禁用 Npugraph_ex:

vllm serve Qwen/Qwen2-7B-Instruct \
  --additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":false}}'

静态内核编译

静态内核编译是一项可选功能,它在编译时预先编译具有固定形状的算子二进制文件,从而降低具有静态或近似静态形状的网络的运行时开销。它默认禁用,必须显式启用。

Note

启用静态内核会在服务启动时的图捕获阶段触发一次编译过程。根据待编译算子数量和模型复杂度,这可能会使启动时间增加几分钟到几十分钟。完成后,后续请求处理不受影响。

离线示例:

from vllm import LLM

model = LLM(
    model="path/to/Qwen2-7B-Instruct",
    additional_config={
        "ascend_compilation_config": {
            "enable_npugraph_ex": True,
            "enable_static_kernel": True,
        }
    }
)
outputs = model.generate("Hello, how are you?")

在线示例:

vllm serve Qwen/Qwen2-7B-Instruct \
  --additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":true, "enable_static_kernel":true}}'

验证静态内核已生效

推荐通过 Ascend Profiling 验证静态内核是否已生效:

  1. 使用 Ascend PyTorch Profiler(torch_npu.profiler)收集正在运行的模型的性能分析跟踪。
  2. 打开生成的 op_statistic.csv 文件。
  3. 查找 op_type 或 name 列中包含关键字 static_kernel 的算子。如果存在此类条目,则静态内核编译已对这些算子生效。

在编译阶段,您会看到一条 Python 警告(默认可见):

Starting static kernel compilation, the build directory is <path>

这表示编译已被触发。如果没有此消息,则表示未启用静态内核,或直接复用了缓存结果。

Super Kernel 优化

Super Kernel 是一项可选的算子二进制融合优化。与源码级融合不同,它作用于已编译的内核二进制文件:识别符合条件的子图,将其子内核合并为一个更大的内核,并根据图依赖关系插入同步。与逐个启动算子相比,这可以减少任务调度等待、启动开销和算子头部开销。

在 vLLM Ascend 中,Super Kernel 优化在 ACLGraph 捕获期间应用。它同时依赖静态内核和 Npugraph_ex:

Super Kernel -> static kernel -> Npugraph_ex

Note

静态内核默认禁用,因此在默认配置下 Super Kernel 也处于禁用状态。当 enable_static_kernel 显式设置为 true 且省略 enable_super_kernel 时,Super Kernel 会跟随静态内核而启用。请显式设置 enable_super_kernel 以覆盖此继承行为。当静态内核禁用时,无法启用 Super Kernel。

并非每个算子都符合 Super Kernel 融合条件。不支持的算子可能会拆分融合范围,因此实际覆盖范围和性能收益取决于模型和算子序列。更改 Super Kernel 设置也会更改静态内核编译配置,并可能导致静态内核缓存被重建。

离线示例:

from vllm import LLM

model = LLM(
    model="path/to/Qwen2-7B-Instruct",
    additional_config={
        "ascend_compilation_config": {
            "enable_npugraph_ex": True,
            "enable_static_kernel": True,
            # `enable_super_kernel` is automatically enabled with `enable_static_kernel=True`.
            # It can also be set explicitly if preferred.
            # "enable_super_kernel": True,
        }
    }
)
outputs = model.generate("Hello, how are you?")

在线示例:

vllm serve Qwen/Qwen2-7B-Instruct \
  --additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":true, "enable_static_kernel":true}}'

若要在不使用 Super Kernel 的情况下使用静态内核:

vllm serve Qwen/Qwen2-7B-Instruct \
  --additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":true, "enable_static_kernel":true, "enable_super_kernel":false}}'

验证 Super Kernel 已启用

当在 ACLGraph 捕获期间应用 Super Kernel 优化时,vLLM Ascend 会输出:

Super kernel optimization is enabled for ACL graph capture.

此消息确认优化步骤已被调用。要验证由此产生的融合覆盖范围和性能收益,请收集 Ascend Profiling 跟踪并检查 kernel_details.csv。将内核/任务条目和延迟与禁用 Super Kernel 时的结果进行比较;分析器还会在 Block Dim 字段中报告生成的 Super Kernel 的启动核心数。

有关 Npugraph_ex 的更多详细信息,请参阅 npugraph_ex 指南。

使用 XliteGraph

XliteGraph 是 Llama 和 Qwen 稠密系列、Qwen MoE 系列、Qwen3-VL 以及 DeepSeek-V3 / V3.2 级别 MoE 模型(包括 GLM-4 / GLM-5 / GLM-5.1 和 MiniMax-M2)的可选图路径。它要求安装 xlite 包,并通过 xlite_graph_config additional-config 键进行配置(参见 配置选项 下的 xlite_graph_config 表)。

首先安装 Xlite:

pip install xlite

仅解码与完整模式

XliteGraph 有两种模式,由 xlite_graph_config.full_mode 选择。在两种模式下,每个批次都按其 Token 数量(所有数据并行 rank 中的最大 Token 数)进行路由:适配 xlite 预分配 Token 预算的批次将由 xlite 运行时执行——无论其包含预填充还是解码——而更大的批次会回退到由 ACLGraph 捕获/重放的原生 runnable。两种模式的区别在于 xlite 预分配的 Token 预算:

模式 full_mode 预分配 Token 预算 由 xlite 运行时处理的批次
仅解码(默认) False max_num_seqs × (1 + num_speculative_tokens) 在解码规模预算内的批次——通常是解码步骤(包括 MTP),以及任何恰好适配的小型预填充/混合批次
完整 True max-num-batched-tokens 任何不超过 max-num-batched-tokens 的批次,即预填充、解码和混合批次均可

在 仅解码模式(默认)下,预算按解码步骤设定:最大运行请求数乘以每个请求的解码 Token 数(1,当启用 MTP 式推测解码时再加上推测 Token)。超出此预算的批次——例如预填充和大型混合批次——会回退到原生 runnable。这会使 xlite 隐藏状态工作区保持较小,并且是推荐选项——Xlite 仍在演进,对于大多数工作负载,仅解码模式性能更好且更稳健。

在 完整模式 下,预算为 max-num-batched-tokens,因此 xlite 运行时同时驱动预填充和解码;只有超过 max-num-batched-tokens 的批次(例如某些性能分析运行)才会回退。由于 xlite 本身管理完整前向,应禁用 ACLGraph 捕获,尤其是在内存受限的情况下,以获得更高的并发和更好的性能。

Note

自 v0.28.0 起,批次按 Token 数量 而非批次注意力状态进行路由:任何位于预分配预算内的批次都会在 xlite 运行时上运行,无论是预填充、解码还是混合。在 v0.28.0 之前,仅解码模式只处理注意力状态为解码的批次——任何包含预填充的批次都会被路由回 ACLGraph——因此小型预填充/混合批次永远无法走 xlite 路径。

支持的模型

xlite 适配器根据 config.json 中的 architectures 字段注册架构。当前支持的集合:

架构 注意力 适配器
LlamaForCausalLM, Qwen2ForCausalLM, Qwen3ForCausalLM MHA StandardXliteModel
Qwen3VLForConditionalGeneration MHA(多模态) StandardXliteModel
Qwen3MoeForCausalLM, Qwen3VLMoeForConditionalGeneration MHA + MoE QwenMoeXliteModel
Glm4MoeForCausalLM MHA + MoE Glm4MoeXliteModel
DeepseekV3ForCausalLM MLA + MoE DeepseekV3XliteModel
DeepseekV32ForCausalLM, GlmMoeDsaForCausalLM DSA + MoE DeepseekV32XliteModel
MiniMaxM2ForCausalLM MHA + MoE MiniMaxM2XliteModel

示例

在 4 张 NPU 卡上以 4 路张量并行提供 Qwen3-30B-A3B(Qwen3MoeForCausalLM,MHA + MoE)服务,并启用专家并行。此处展示完整模式;若使用仅解码模式,请移除 "full_mode": true。

离线示例:

import os

from vllm import LLM

os.environ["HCCL_BUFFSIZE"] = "1024"
os.environ["TASK_QUEUE_ENABLE"] = "1"
os.environ["OMP_PROC_BIND"] = "false"
os.environ["HCCL_OP_EXPANSION_MODE"] = "AIV"
os.environ["PYTORCH_NPU_ALLOC_CONF"] = "expandable_segments:True"

llm = LLM(
    model="path/to/Qwen3-30B-A3B",
    tensor_parallel_size=4,
    enable_expert_parallel=True,
    enforce_eager=True,  # recommended in xlite full mode without speculative decoding
    additional_config={"xlite_graph_config": {"enabled": True, "full_mode": True}},
)
outputs = llm.generate("Hello, how are you?")

在线示例:

export HCCL_BUFFSIZE=1024
export TASK_QUEUE_ENABLE=1
export OMP_PROC_BIND=false
export HCCL_OP_EXPANSION_MODE=AIV
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

vllm serve path/to/Qwen3-30B-A3B \
  --tensor-parallel-size 4 \
  --enable-expert-parallel \
  --enforce-eager \
  --additional-config '{"xlite_graph_config": {"enabled": true, "full_mode": true}}'

有关 Xlite 的更多详细信息,请参阅 Xlite README。

常见限制和注意事项

  • 应将 XliteGraph 视为一种替代图路径,而不是在所有场景下都作为 ACLGraph 的直接替换方案。
  • 模型和后端支持仍在持续完善中,因此适用于某个模型系列的配置,可能尚不推荐用于其他模型系列。
  • 编码器-解码器模型目前不会保留 FULL_AND_PIECEWISE;在 Ascend 上,它们会根据编译支持情况回退到 PIECEWISE 或 NONE。

回退到即时模式

如果在图模式遇到问题,可以通过设置 enforce_eager=True 临时回退到即时模式。

如果 ACL 图捕获失败,并且错误文本中出现已确认的流资源特征,例如 207008 与 Stream resources are insufficient 或 Insufficient_Stream_Resources 同时出现,vLLM Ascend 会重新抛出该捕获失败,并给出针对性的缓解建议。实际中,主要调整手段包括:升级到更新的 HDK/CANN 软件栈、减小 cudagraph_capture_sizes、降低 max_cudagraph_capture_size,或者在工作负载主要为均匀解码时优先使用 FULL / FULL_DECODE_ONLY。

离线示例:

from vllm import LLM

llm = LLM(model="path/to/your/model", enforce_eager=True)
outputs = llm.generate("Hello, how are you?")

在线示例:

vllm serve path/to/your/model --enforce-eager

参考

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend