首页
/ 深入 vLLM 的 torch.compile 集成:编译缓存、动态形状、图切分与分块 CUDA Graphs

深入 vLLM 的 torch.compile 集成:编译缓存、动态形状、图切分与分块 CUDA Graphs

2026-09-04 09:24:07作者:沈韬淼Beryl

在 vLLM 的 V1 架构中,torch.compile 默认开启,是整个框架性能与启动体验的关键组成部分。本文以官方设计文档 torch_compile.md 为骨架,结合 meta-llama/Llama-3.2-1B 的 DEBUG 级日志,带你完整走一遍 torch.compile 在 vLLM 中的工作流程:从编译缓存目录如何确定、Dynamo 如何追踪 Python 代码、计算图如何被切分与编译,到 Inductor 的自动调优和分块 CUDA Graph 捕获。读完之后,你将能够看懂 vLLM 的编译日志、合理配置动态形状模式(dynamic_shapes_config)、用 compile_sizescudagraph_capture_sizes 微调性能,并知道在部署场景下如何复用编译缓存以大幅缩短实例启动时间。

整篇文章的分析都以一条可复现的调试命令为基础,开启 DEBUG 日志并启动一个常见的 Llama 模型:

VLLM_LOGGING_LEVEL=DEBUG vllm serve meta-llama/Llama-3.2-1B

一、编译缓存(Compilation Cache)

在 DEBUG 日志中可以看到类似这样一行输出:

INFO 03-07 03:06:55 [backends.py:409] Using cache directory: ~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0 for vLLM's torch.compile

vLLM 会把所有可能影响编译产物的因素都纳入考虑,据此决定一个专门的目录来存放全部编译产物。这意味着在实际部署中,你可以直接把 ~/.cache/vllm/torch_compile_cache 整个目录拷贝到新的环境里,从而省去大量编译时间、显著加快 vLLM 实例的启动。

从源码结构看,缓存目录的生成逻辑位于 backends.py:后端会把四类因素分别哈希后拼接成一个 10 位的 SHA-256 前缀作为缓存键:

  • env_hash:运行环境相关因素;
  • config_hash:由 vllm_config.compute_hash() 得到,涵盖所有相关配置(各配置类中的 compute_hash 函数,位于 config 目录,如 compilation.py 中 CompilationConfig.compute_hash);
  • code_hash:对 forward 函数及其调用链中所有被 Dynamo 追踪到的文件内容做 SHA-256(即日志中的 “Traced files” 列表),任何一处被追踪代码的修改都会导致缓存失效并触发重新编译;
  • compiler_hash:PyTorch 编译器的相关配置(见 compiler_interface.py 中的 compute_hash 函数)。

最终目录形如 ~/.cache/vllm/torch_compile_cache/{hash_key}/rank_{rank}_{dp_rank},按并行 rank 进一步隔离。

缓存默认开启,以及 vLLM 的两个独特保证

考虑到上述全部因素,vLLM 通常可以保证缓存是安全可用的、不会引发意外行为,因此缓存默认启用。如果你想调试编译过程,或者怀疑缓存导致了问题,可以通过设置环境变量 VLLM_DISABLE_COMPILE_CACHE=1 来禁用它。在源码层面,这个开关由 compiler_interface.py 中的 is_compile_cache_enabled 统一裁决,它同时检查 VLLM_DISABLE_COMPILE_CACHE、PyTorch 的 force_disable_caches 以及 vLLM 传入的 Inductor 额外配置。

vLLM 的 torch.compile 集成还有一个独特之处:它保证在开始服务任何请求之前,所有编译都已完成,没有任何请求会触发新的编译。否则引擎会阻塞在该请求上,响应时间会出现不可预期的尖峰。

默认情况下,缓存以二进制文件格式保存编译产物。如果你需要与生成的代码交互以进行调试,可以把编译配置中的 compile_cache_save_format 字段设为 unpacked,或者不设置该字段而改用环境变量 VLLM_COMPILE_CACHE_SAVE_FORMAT=unpacked。对应实现见 CompilationConfig.compile_cache_save_format,其默认值取自环境变量,可选值为 binary(多进程安全)与 unpacked(目录结构,便于检查但不多进程安全)。

二、动态形状与 vLLM 的 guard 丢弃策略(Dynamic Shapes)

torch.compile 在设计上会毫不犹豫地针对动态形状添加 guard(守卫),这与 vLLM 的做法相冲突——vLLM 会丢弃(drop)这些 guard,因为其中很多 guard 实际上是重要的。理解这一点是配置动态形状模式的前提。

torch.compile 提供两种动态形状:backedunbacked

  • backedtorch.compile 会对 backed 动态形状添加 guard,并且不保证不会添加 guard。用户代码、Dynamo、Inductor 和 autograd 都可能添加 guard。此外,对于 0/1 特化(specialization),即使没有在这些区间上遇到分支,backed 符号也会被无条件特化为 0、1 或 >=2。
  • unbacked:保证不会被添加 guard,也不会被 0/1 特化。但风险在于:当遇到需要其具体数值的分支且未定义显式的 unbacked 处理时,可能抛出 data dependent error(DDE)。框架正朝着“不再抛 DDE 而是选择通用路径”的方向演进。unbacked 的一个缺点是可能因性能 bug 或选择通用路径而错失优化机会(例如,当无法用符号证明输入连续时,在调用 contiguous()reshape() 的函数中假设输入非连续,并引入一次 clone 的拷贝)。

backed_size_oblivious 是一个标志,它让框架在定义了显式 unbacked 处理的地方,把 backed 符号当作 unbacked 处理。在该模式下,框架代码中的 0/1 特化大多会被避免。但 torch.compile 仍不保证不添加 guard(尤其是用户代码或自定义 pass 可能引入),且该模式在 PyTorch 编译栈中属于实验特性、未来可能弃用。即便如此,它仍是比 backed 更安全、性能下降概率比 unbacked 更低的折中选项。

配置动态形状:三种模式

DynamicShapesConfig 允许通过设置 type 字段来控制动态形状行为,可在三种模式中选择:BACKED(默认)、UNBACKEDBACKED_SIZE_OBLIVIOUS。枚举定义见 DynamicShapesType

离线推理示例(LLM 类)

使用 LLM 类做离线推理时,可以通过 compilation_config 参数配置动态形状:

from vllm import LLM, SamplingParams
from vllm.config.compilation import CompilationConfig, DynamicShapesConfig, DynamicShapesType

# 示例:使用 backed_size_oblivious(实验性,比 backed 更安全)
llm = LLM(
    model="meta-llama/Llama-3.2-1B",
    compilation_config=CompilationConfig(
        dynamic_shapes_config=DynamicShapesConfig(
            type=DynamicShapesType.BACKED_SIZE_OBLIVIOUS
        )
    )
)

# 示例:使用 unbacked(对 guard 的最强保证)
llm = LLM(
    model="meta-llama/Llama-3.2-1B",
    compilation_config=CompilationConfig(
        dynamic_shapes_config=DynamicShapesConfig(
            type=DynamicShapesType.UNBACKED
        )
    )
)

# 生成输出
prompts = ["Hello, my name is", "The future of AI is"]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
outputs = llm.generate(prompts, sampling_params)

在线服务示例(vllm serve)

使用 vllm serve 在线服务时,可以通过 --compilation-config 标志配置:

# 示例:使用 unbacked
vllm serve meta-llama/Llama-3.2-1B \
  --compilation-config '{"dynamic_shapes_config": {"type": "unbacked"}}'

# 替代写法:点号记法(单个值时更简洁)
vllm serve meta-llama/Llama-3.2-1B -cc.dynamic_shapes_config.type=unbacked

如何选择模式

  • BACKED(默认):当你愿意接受 guard 可能被“不安全地丢弃”(guard 可能被非健全地添加然后被忽略)以换取最大性能时使用。
  • UNBACKED:当你需要最强的“无 guard”保证时使用。这是最保守的选项,但可能错失一些优化机会。
  • BACKED_SIZE_OBLIVIOUS:当你想在避免 guard 与性能之间取得平衡时使用。这个实验性模式比 BACKED 更安全,但又不像 UNBACKED 那样保守。

此外,DynamicShapesConfig 还有一个调试字段 evaluate_guards(见 DynamicShapesConfig):开启后,Dynamo 一旦因动态形状而添加 guard 就会触发失败,可用于检测动态形状 guard 是否真的被引入。

三、Python 代码编译:Dynamo 图捕获

在 DEBUG 日志中,Python 代码编译(即 Dynamo 的图捕获)阶段会输出如下内容:

DEBUG 03-07 03:06:52 [decorators.py:203] Start compiling function <code object forward at 0x7f08acf40c90, file "xxx/vllm/model_executor/models/llama.py", line 339>

DEBUG 03-07 03:06:54 [backends.py:370] Traced files (to be considered for compilation cache):
DEBUG 03-07 03:06:54 [backends.py:370] xxx/torch/_dynamo/polyfills/builtins.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/torch/nn/modules/container.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/torch/nn/modules/module.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/attention/layer.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/distributed/communication_op.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/distributed/parallel_state.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/custom_op.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/layers/activation.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/layers/layernorm.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/layers/linear.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/layers/rotary_embedding.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/layers/vocab_parallel_embedding.py
DEBUG 03-07 03:06:54 [backends.py:370] xxx/vllm/model_executor/models/llama.py

DEBUG 03-07 03:07:07 [backends.py:462] Computation graph saved to ~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/computation_graph.py
DEBUG 03-07 03:07:07 [wrapper.py:105] Dynamo transformed code saved to ~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/transformed_code.py

这一段展示的是对 xxx/vllm/model_executor/models/llama.py:339 处函数——也就是被编译模型的 forward 函数——的追踪过程。在 forward 过程中,还有其他函数被 Dynamo 调用并内联,如日志所示:包括来自 torch/nn/modules/module.py 的 PyTorch 函数(PyTorch nn.Module 使用它们,因为模块属性访问会触发函数调用),以及来自 vLLM 的通信、注意力、激活等函数。所有被追踪到的文件都会参与缓存目录的决策——这正是上文“code_hash 覆盖 traced files”的具体含义:上述任何一个文件的改动都会触发缓存失效并导致重新编译。

Dynamo 编译的产物是一个新函数,保存在 ~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/transformed_code.py。通常,这个函数会从模块中解包出张量,然后传给被追踪到的计算图。计算图本身保存在同一目录下的 computation_graph.py 中。

四、计算图处理:形状标注、符号形状与注意力自定义算子

计算图为每个张量都带有形状标注。输入包括 input ids、position ids 以及模型的权重和缓冲区(weights 和 buffers),输出是最终的 hidden states。注意,lm head 投影与采样操作不在图内。

由于绝大多数输入是模型权重和缓冲区,在整个模型生命周期中保持不变,因此它们具有静态形状。只有 input ids 和 position ids 具有符号形状(symbolic shapes),即形状可以逐批次变化,且它们共享同一套符号形状。换言之,对计算图而言,唯一会变化的尺寸就是 batch size(当前 forward pass 处理的 token 数)。

注意力操作比较复杂,需要与形状复杂的 kv cache 交互。幸运的是,注意力操作的输出形状与输入 query 的形状相同。因此 vLLM 把整个注意力操作封装成一个 PyTorch 自定义算子 torch.ops.vllm.unified_attention_with_output,使 Dynamo 不会去探查其内部操作。这样一来,虽然注意力本身很复杂,vLLM 依然可以从 Dynamo 的视角把整个模型的计算图捕获为 full-graph。在 CompilationConfig 源码 中可以看到用于分块 CUDA Graph 的注意力算子列表 _attention_opsvllm::unified_attention_with_output 排在首位,还包括 MLA、Mamba、线性注意力等一系列变体。

计算图随后会按照 splitting_ops(通常就是注意力操作)进一步切分成若干片段。因此,在 computation_graph.py 文件中可以见到大量子模块(submodule),每个子模块就是切分后的一段图:

  • 注意力操作本身是一个子模块;
  • 从一次注意力操作到下一次注意力操作之间的图,是一个子模块。

每个子模块都可以用其索引来标识,并会被单独处理。切分行为由 splitting_ops 配置控制,其语义见 CompilationConfig.splitting_ops:默认为注意力算子;设为空列表 [] 则不排除任何算子,适合整图 CUDA Graph。

五、计算图编译:Inductor、子图复用与自动调优

DEBUG 日志中还能看到 Inductor 编译阶段的输出:

DEBUG 03-07 03:52:37 [backends.py:134] store the 0-th graph for shape None from inductor via handle ('fpegyiq3v3wzjzphd45wkflpabggdbjpylgr7tta4hj6uplstsiw', '~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/inductor_cache/iw/ciwzrk3ittdqatuzwonnajywvno3llvjcs2vfdldzwzozn3zi3iy.py')
DEBUG 03-07 03:52:39 [backends.py:134] store the 1-th graph for shape None from inductor via handle ('f7fmlodmf3h3by5iiu2c4zarwoxbg4eytwr3ujdd2jphl4pospfd', '~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/inductor_cache/ly/clyfzxldfsj7ehaluis2mca2omqka4r7mgcedlf6xfjh645nw6k2.py')
...
DEBUG 03-07 03:52:45 [backends.py:134] store the 15-th graph for shape None from inductor via handle ('f7fmlodmf3h3by5iiu2c4zarwoxbg4eytwr3ujdd2jphl4pospfd', '~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/inductor_cache/ly/clyfzxldfsj7ehaluis2mca2omqka4r7mgcedlf6xfjh645nw6k2.py')
DEBUG 03-07 03:52:45 [backends.py:134] store the 16-th graph for shape None from inductor via handle ('fvj3ccoi7m34f3dnr4itmu55mmun44l5xymwhrjlwisylsk7q6jy', '~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/inductor_cache/tf/ctfftkglj7b4lcttq5cymx6cew372uoauupqn6ldsvpiucavqcjc.py')

这表示第一块计算图(符号形状下记为 shape None)由 Inductor 编译(键为 fpegyiq3...),编译出的内核保存在 inductor_cache/ 下的 .py 文件中——你可以直接打开该文件,查看 Inductor 最终实际运行的代码。

还有一个值得注意的细节:第 1 块到第 15 块图共用同一个编译键,而第 0 块和第 16 块则是不同的键。这是预期行为:因为按注意力算子切分后,我们得到 3 个唯一的子图

  • 第一个注意力之前的首层;
  • 每个中间层(从一次注意力到下一次注意力);
  • 最后一个注意力之后的末层。

因此,16 层 Llama 只需要编译 3 份唯一的子图,其余层直接复用。

如果缓存目录已经存在(例如第二次运行相同代码),则会看到:

DEBUG 03-07 04:00:45 [backends.py:86] Directly load the 0-th graph for shape None from inductor via handle ('fpegyiq3v3wzjzphd45wkflpabggdbjpylgr7tta4hj6uplstsiw', '~/.cache/vllm/torch_compile_cache/1517964802/rank_0_0/inductor_cache/iw/ciwzrk3ittdqatuzwonnajywvno3llvjcs2vfdldzwzozn3zi3iy.py')

此时 Inductor 编译被完全跳过(bypassed),直接从磁盘加载上次得到的编译产物。

为特定形状编译:compile_sizes 与自动调优

上面的示例只用 Inductor 针对“通用形状”(符号形状)编译。你也可以为一些特定形状编译,例如:

vllm serve meta-llama/Llama-3.2-1B \
  --compilation_config '{"compile_sizes": [1, 2, 4, 8]}'

这样会为 batch size 1, 2, 4, 8 各额外编译一个专属内核。此时计算图中所有形状都是静态且已知的,vLLM 会开启自动调优(auto-tuning)来寻找最优性能。首次运行会比较慢,但下次运行时可以直接跳过调优、直接运行调优后的内核。这一能力对应 CompilationConfig.compile_sizes / compile_ranges_endpoints

当所有形状都已知时,torch.compile 可以比较不同配置,经常能找到比默认配置更好的内核配置。例如可以见到如下日志:

AUTOTUNE mm(8x2048, 2048x3072)
  triton_mm_4 0.0130 ms 100.0% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=128, BLOCK_M=16, BLOCK_N=32, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=5, num_warps=2
  triton_mm_8 0.0134 ms 97.4% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=128, BLOCK_M=16, BLOCK_N=64, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=5, num_warps=4
  triton_mm_12 0.0148 ms 87.7% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=128, BLOCK_M=16, BLOCK_N=128, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=4, num_warps=4
  mm 0.0160 ms 81.6%
  triton_mm_16 0.0165 ms 78.7% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=64, BLOCK_M=16, BLOCK_N=128, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=5, num_warps=8
  triton_mm_3 0.0199 ms 65.4% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=32, BLOCK_M=16, BLOCK_N=32, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=5, num_warps=2
  triton_mm_1 0.0203 ms 64.2% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=128, BLOCK_M=16, BLOCK_N=32, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=2, num_warps=2
  triton_mm_7 0.0203 ms 64.1% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=64, BLOCK_M=16, BLOCK_N=64, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=3, num_warps=4
  triton_mm_2 0.0208 ms 62.5% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=32, BLOCK_M=16, BLOCK_N=64, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=5, num_warps=4
  triton_mm_11 0.0215 ms 60.5% ACC_TYPE='tl.float32', ALLOW_TF32=False, BLOCK_K=64, BLOCK_M=16, BLOCK_N=128, B_PROLOGUE_CAST_TYPE=None, EVEN_K=True, GROUP_M=8, num_stages=3, num_warps=4
SingleProcess AUTOTUNE benchmarking takes 2.0428 seconds and 7.5727 seconds precompiling

含义是:对于 8x2048x3072 的矩阵乘法,torch.compile 尝试了各种配置的 Triton 模板,其速度明显快于默认代码(默认代码会分派到 cuBLAS 库)。

遗憾的是,由于自动调优耗时较长(从数秒到数分钟不等,取决于模型大小与 batch size),尽管调优结果可以被缓存供以后使用,出于用户体验考虑,vLLM 默认关闭了针对特定形状的编译调优。如果你追求极致性能,推荐通过编译特定形状来开启它。

六、CUDA Graph 捕获:分块(Piecewise)与全图(Full)

vLLM 的 V1 架构使用与分块编译对齐的 piecewise cudagraph(分块 CUDA Graph)。整图按上文方式切分后,vLLM 只对“注意力操作之间”的图片段捕获 CUDA Graph(包括第一个注意力之前的首段、以及所有注意力之后的末段)。这基于一个常见观察:注意力之间的计算通常是 token 级的、易于被 CUDA Graph 处理;而注意力操作要兼容 CUDA Graph 则不那么简单。因此,让注意力以 eager 模式运行、其余操作跑在 CUDA Graph 中,既保留了注意力操作的灵活性,又拿到了图捕获的收益。

分块 CUDA Graph 还具备细粒度的内存管理:其目的是只把注意力内核排除在图之外,而把其余所有模块以及内存分配操作都保留在图内。这也是为什么 V1 中注意力操作把输出张量作为输入的原因。

CUDA Graph 的捕获与管理由编译器后端负责,当 batch size 有对应的已捕获图时直接重放(replay)。模型调用方(model runner)只需要保证正确管理输入缓冲区即可,所有中间缓冲区都由编译器后端自动管理。

默认情况下,vLLM 会自行确定一组要捕获的 CUDA Graph 尺寸,你也可以用 cudagraph_capture_sizes 配置覆盖:

vllm serve meta-llama/Llama-3.2-1B \
  --compilation-config '{"cudagraph_capture_sizes": [1, 2, 4, 8]}'

这样只会为指定尺寸捕获 CUDA Graph,便于对图捕获做细粒度控制。未显式指定时,尺寸列表按 max_cudagraph_capture_size 的注释 中的规律自动生成:[1, 2, 4] + range(8, 256, 8) + range(256, max_size + 1, 16),其中 max_cudagraph_capture_size 默认上限为 512(数据中心 Blackwell GPU 上为 1024),以避免紧张显存下的小 max_num_seqs 场景 OOM,并限制增大启动时间和显存占用的大图捕获。

全图 CUDA Graph 捕获

如果使用与 CUDA Graph 兼容的注意力后端,也可以把注意力纳入 CUDA Graph 之中,在部分场景(如小模型或 MOE 的 decode 速度)下能进一步提升性能。更多细节参见仓库中的 CUDA Graphs 设计文档。在 CUDAGraphMode 枚举中,V1 的默认模式是 FULL_AND_PIECEWISE:decode 批次使用整图 CUDA Graph,prefill 与混合批次使用分块 CUDA Graph。

七、快速参考:与本文相关的 CompilationConfig 关键字段

结合 CompilationConfig 的定义,把前文涉及的关键配置项汇总如下:

配置项 默认值 作用
mode 3(VLLM_COMPILE 编译方式:0 不编译、1 标准 torch.compile、2 Dynamo 单次追踪、3 vLLM 自定义 Inductor 后端(带缓存、分块编译、形状特化与自定义 pass)
cache_dir 空(自动生成) 编译产物目录;为空时按 env/config/code/compiler 四类哈希自动生成
compile_cache_save_format binary binary 多进程安全;unpacked 保存为目录结构便于调试,受环境变量 VLLM_COMPILE_CACHE_SAVE_FORMAT 影响
splitting_ops 注意力算子列表 分块编译的切分点;空列表 [] 表示不排除任何算子,适合整图 CUDA Graph
compile_sizes None 为指定 batch size 额外编译静态形状内核并开启 auto-tuning
cudagraph_mode FULL_AND_PIECEWISE(V1) CUDA Graph 模式:NONE / PIECEWISE / FULL / FULL_DECODE_ONLY / FULL_AND_PIECEWISE
cudagraph_capture_sizes 自动推断 指定要捕获 CUDA Graph 的 batch size 集合
max_cudagraph_capture_size 512(Blackwell 数据中心卡 1024) 自动生成的捕获尺寸上限
dynamic_shapes_config DynamicShapesType.BACKED 动态形状模式:BACKED / UNBACKED / BACKED_SIZE_OBLIVIOUS

小结

vLLM 的 torch.compile 集成并非简单地调用 PyTorch 默认管线,而是一套围绕“启动即完成编译、缓存可整目录复用、按注意力切分编译与图捕获、注意力走 eager 保留灵活性”设计的完整方案:Dynamo 追踪 forward 及其调用链并记录所有 traced files 作为缓存失效依据;计算图被 splitting_ops 切分为首段/中段/末段三类唯一子图,由 Inductor 分别编译并以文件形式落盘;可选地为小 batch 静态形状开启 auto-tuning;最后用分块 CUDA Graph 捕获注意力之外的全部计算。理解这条链路之后,你就能用 DEBUG 日志(VLLM_LOGGING_LEVEL=DEBUG)诊断编译问题、用 VLLM_DISABLE_COMPILE_CACHE=1unpacked 格式排查缓存异常,并用 dynamic_shapes_configcompile_sizescudagraph_capture_sizes 三个旋钮在正确性与性能之间做取舍。

登录后查看全文
热门项目推荐
相关项目推荐