ACL 图¶
概述¶
ACL 图是 vLLM 静态图执行在 Ascend 上的实现。上游 vLLM 和 PyTorch 文档已经描述了通用图模型,包括 CUDAGraphMode、运行时调度、批处理描述符、分桶和填充,以及全图和分段图的定义。本文档聚焦于 vllm-ascend 中 Ascend 特有的内容:平台集成点、ACL 图捕获引入的额外约束,以及在重放期间保持注意力参数正确的机制。
在 Ascend 上,设计目标与上游静态图执行相同:降低小型和中型运行时形状的主机启动开销。实现边界不同。vLLM 提供通用调度路径,而 vllm-ascend 提供 ACL 图重放所需的平台封装、捕获大小裁剪以及注意力特定的更新逻辑。
前提条件和参考资料¶
- 上游 vLLM 关于通用图概念的设计文档:CUDA Graphs。
- PyTorch 关于通用捕获和重放语义的图文档:Accelerating PyTorch with CUDA Graphs。
- Ascend 用于操作启用的用户指南:Graph Mode Guide。
- 现有仓库设计说明:ACL Graph
本文档有意不重新解释上游主题,例如图模式选择、调度器行为、批处理描述符构造、捕获分桶、填充策略,或全图执行与分段图执行的通用含义。
ACL 图如何融入 vLLM¶
vLLM 负责通用静态图流程。在 Ascend 上,NPUPlatform.get_static_graph_wrapper_cls() 返回 vllm_ascend.compilation.acl_graph.ACLGraphWrapper,这是 vLLM 启用静态图模式时使用的平台特定封装。
ACLGraphWrapper 负责:
- 从前向上下文中读取运行时模式和
batch_descriptor, - 决定是立即执行、捕获新的 ACL 图,还是重放已缓存的 ACL 图,
- 按批处理描述符缓存图条目,
- 保留 Ascend 后端所需的图池和重放簿记。
该封装不定义上游调度策略。它假设运行时模式和批处理描述符已由 vLLM 正确选择,然后针对该具体运行时形状应用 Ascend 捕获或重放。
捕获大小与分桶¶
vLLM 图重放需要稳定的运行时形状,因此 vLLM 不会尝试捕获所有可能的批处理形状。相反,它准备一组有限的捕获大小,并将运行时批处理调度到最近的支持大小。如果运行时批处理大于配置的最大捕获大小,则跳过图模式,执行回退到立即模式。
更多信息,请参阅上游 CUDA Graphs 设计文档。
在 Ascend 上,这种通用上游分桶策略仍是起点,但最终捕获大小可能因平台特定约束而进一步减少:
- 序列并行过滤可能会移除不支持的大小,
- 运行时资源限制仍可能阻止某些已配置大小的捕获,
- 某些运行时模式可能在捕获开始前被规范化。
Ascend 特定设计约束¶
捕获广度仍受运行时资源约束¶
当所选图大小消耗的运行时资源超过当前后端可提供的资源时,ACL 图捕获可能会失败。分段模式是最敏感的情况,因为它捕获许多子图,且总捕获成本随模型深度和配置的大小覆盖范围扩展。
当前实现可以针对图容量降低的硬件配置裁剪捕获大小集合。它还会拦截 vllm_ascend/compilation/acl_graph.py 中确认的捕获时流资源签名,并以更清晰的缓解指导重新抛出。
实际上,这意味着当捕获失败时,用户应将 cudagraph_capture_sizes 和 max_cudagraph_capture_size 视为主要调优杠杆。较新的 HDK/CANN 组合可以实质性提升 ACL 图容量,而通信密集型配置可能仍需要更小的配置大小集合。
平台模式规范化比通用上游行为更严格¶
Ascend 当前在 vllm_ascend.platform.NPUPlatform.check_and_update_config() 中收窄了一些通用上游模式。
- 请求全图模式的编码器-解码器模型,在启用 vLLM 编译时回退到
PIECEWISE,否则回退到NONE。 - 对于 ACL 图路径,
use_inductor被禁用。 - 根据配置,Xlite 图模式可以禁用 ACL 图全模式,或回退到
FULL_DECODE_ONLY。
这些检查记录了当前 Ascend 后端可以安全执行的上游图行为子集。
关键 Ascend 特定机制¶
全图重放的主机端注意力参数更新¶
Ascend 上的全图重放存在一个上游通用文档未详细覆盖的额外问题:即使整体图是静态的,某些注意力算子也需要运行时元数据更新。Ascend 实现通过将图捕获与主机端任务参数更新分离来处理此问题。
流程如下:
- 捕获期间,注意力后端记录每个图的任务句柄、事件、工作区,以及必须刷新的张量或元数据的弱引用。
- 重放前,
update_full_graph_params()调用后端特定的update_graph_params()实现。 - 该后端在更新流上运行参数刷新,在底层注意力算子启动周围使用
torch.npu.graph_task_update_begin(...)和torch.npu.graph_task_update_end(...)。 - 使用
torch.npu.ExternalEvent对象来强制主机端更新流与重放流之间的顺序。
该机制在如下注意力后端中实现:
vllm_ascend/attention/attention_v1.pyvllm_ascend/attention/mla_v1.pyvllm_ascend/attention/context_parallel/attention_cp.pyvllm_ascend/attention/context_parallel/mla_cp.py
关键设计点是,Ascend 完整图支持依赖于后端提供的 update_graph_params() 钩子。如果没有该钩子,仅靠捕获不足以重放正确的注意力状态。
重放顺序与同步¶
ACLGraphWrapper 在通用路径中于重放前同步当前流,以确保主机侧参数更新与将消费这些更新的图执行保持一致。这在异步调度或多线程执行中尤其相关。
如果顺序未被保持,迭代 i 的参数更新可能被迭代 i-1 的重放观察到,或者迭代 i 的重放可能在其自身参数更新完成之前开始。实际上,这意味着注意力算子可能带着不匹配的运行时元数据运行,从而导致错误结果、精度问题,甚至挂起。代码为主完整图 eagle 场景保留了一条更窄的路径,但总体设计假设相同:重放不得超越待处理的参数更新工作。
Ascend 上的完整图与分段图¶
上游文档已在语义上定义了完整图和分段图。在 Ascend 上,实际差异由后端支持和资源开销驱动。
分段模式¶
分段模式是保守路径。它依赖通用的 vLLM 拆分执行策略,然后对编译路径选择的非注意力段应用 ACL 图捕获。在 Ascend 上,该模式目前支持更广泛,但它对流压力也最敏感,因为捕获的图数量随模型深度增长。
完整图模式¶
当注意力后端能够通过 update_graph_params() 支持运行时参数修补时,完整图模式是更偏向性能的路径。在 Ascend 上,完整图支持与这些注意力特定的更新钩子、工作区缓存以及重放顺序保证相关联。
诊断与运维说明¶
- 确认图模式已启用的最简单方式是启用 cudagraph 指标并保持日志统计启用。在 CLI 使用中,使用
--cudagraph-metrics,并且不要传入--disable-log-stats。在 Python 使用中,设置cudagraph_metrics=True和disable_log_stats=False。然后检查输出的指标和日志。 - 性能分析也可以确认是否正在发生重放,开发者在本地调试时可以在重放前添加临时打印,但这些是次要方法,此处不再展开。
- 捕获大小选择遵循上游配置,并进行平台过滤和硬件特定剪枝。
ACLGraphWrapper为已识别的旧 HDK 和流资源捕获错误提供指导。 - 在调试模式下,
ACLGraphWrapper会断言重放使用与捕获期间记录的相同张量地址。 - 对于图执行内部的调试,仓库还在
vllm_ascend.utils中提供了图感知打印辅助函数,但这些属于开发者诊断,而不是执行设计的一部分。
相关文件¶
vllm_ascend/platform.py,模式规范化、平台钩子和静态图包装器选择。vllm_ascend/compilation/acl_graph.py,ACL 图包装器、捕获和重放缓存、图参数容器以及完整图更新分发。vllm_ascend/compilation/acl_graph.py,运行时 ACL 图捕获、重放以及捕获失败指导。vllm_ascend/attention/attention_v1.py,完整图注意力参数捕获和更新逻辑。vllm_ascend/attention/mla_v1.py,MLA(Multi-Head Latent Attention)特定的完整图参数捕获和更新逻辑。vllm_ascend/attention/context_parallel/attention_cp.py,上下文并行注意力更新路径。vllm_ascend/attention/context_parallel/mla_cp.py,上下文并行 MLA 更新路径。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend