vLLM Ascend 中的补丁

vLLM Ascend 中的补丁#

vLLM Ascend 是 vLLM 的一个平台插件。由于 vLLM 和 vLLM Ascend 的发布周期不同以及硬件限制,我们需要对 vLLM 中的部分代码打补丁,以使其兼容 vLLM Ascend。

在 vLLM Ascend 代码中,我们提供了一个补丁模块 vllm_ascend/patch 来适配 vLLM 的变更。

原则#

我们需要牢记,补丁并非使 vLLM Ascend 兼容的最佳方式,它只是一个临时解决方案。最佳方式是将修改贡献给 vLLM,使其原生兼容 vLLM Ascend。在 vLLM Ascend 中,我们遵循以下补丁策略基本原则:

  1. 少即是多。除非是当前唯一的方法,否则请不要打补丁。

  2. 一旦添加了补丁,必须描述未来移除该补丁的计划。

  3. 随时欢迎清理补丁代码。

工作原理#

vllm_ascend/patch 中,你可以看到如下的代码结构:

vllm_ascend
├── patch
│   ├── platform
│      ├── patch_xxx.py
│   ├── worker
│      ├── patch_yyy.py
└───────────
  • platform:此目录中的补丁代码用于修补 vLLM 主进程中的代码。它在 vLLM 初始化时,由 vllm_ascend/platform::NPUPlatform::pre_register_and_update 在非常早期阶段调用。

    • 对于在线模式,vLLM 进程在解析命令行参数时,会在 vllm/vllm/engine/arg_utils.py::AsyncEngineArgs.add_cli_args 处调用平台补丁。

    • 对于离线模式,vLLM 进程在解析输入参数时,会在 vllm/vllm/engine/arg_utils.py::EngineArgs.create_engine_config 处调用平台补丁。

  • worker:此目录中的补丁代码用于修补 vLLM worker 进程中的代码。它在 vLLM worker 进程初始化时,由 vllm_ascend/worker/worker::NPUWorker::__init__ 调用。

    • 对于在线和离线模式,vLLM 引擎核心进程在初始化 worker 进程时,都会在 vllm/vllm/worker/worker_base.py::WorkerWrapperBase.init_worker 处调用 worker 补丁。

如何编写补丁#

在编写补丁之前,遵循上述原则,我们应该修补最少的代码。如果必要,我们可以在 platformworker 文件夹中修补代码。以下是一个修补 vLLM 中 distributed 模块的示例。

  1. 确定我们需要修补哪个版本的 vLLM。例如,经过分析,这里我们想要同时修补 vLLM 的 0.10.0 版本和 main 分支。

  2. 确定我们需要修补哪个进程。例如,这里的 distributed 属于 vLLM 主进程,因此我们应该修补 platform

  3. 在正确的文件夹中创建补丁文件。文件应命名为 patch_{module_name}.py。这里的示例是 vllm_ascend/patch/platform/patch_distributed.py

  4. 在新文件中编写你的补丁代码。以下是一个示例:

    import vllm
    
    def patch_destroy_model_parallel():
        # your patch code
        ...
    
    vllm.distributed.parallel_state.destroy_model_parallel = patch_destroy_model_parallel
    
  5. __init__.py 中导入补丁文件。在此示例中,将 import vllm_ascend.patch.platform.patch_distributed 添加到 vllm_ascend/patch/platform/__init__.py 中。

  6. vllm_ascend/patch/__init__.py 中添加补丁的描述。描述格式如下:

    # ** File: <The patch file name> **
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #   1. `<The target patch module in vLLM>`
    #    Why:
    #       <Describe the reason why we need to patch>
    #    How:
    #       <Describe the way to patch>
    #    Related PR (if no, explain why):
    #       <Add a link to the related PR in vLLM. If there is no related PR, explain why>
    #    Future Plan:
    #       <Describe the future plan to remove the patch>
    
  7. 添加单元测试和端到端测试。vLLM Ascend 中任何新添加的代码也应包含单元测试和端到端测试。你可以在测试指南中找到更多详细信息。

限制#

  1. 在 V1 引擎中,vLLM 启动三种进程:主进程、EngineCore 进程和 Worker 进程。目前 vLLM Ascend 默认只能修补主进程和 Worker 进程中的代码。如果你想修补 EngineCore 进程中运行的代码,你需要在设置期间完全修补 EngineCore 进程。完整代码位于 vllm.v1.engine.core。请完全重写 EngineCoreProcDPEngineCoreProc

  2. 如果你运行的是编辑过的 vLLM 代码,vLLM 的版本可能会自动更改。例如,如果你基于 v0.9.n 运行编辑后的 vLLM,vLLM 的版本可能会变为 v0.9.nxxx。在这种情况下,vLLM Ascend 中针对 v0.9.n 的补丁将无法按预期工作,因为 vLLM Ascend 无法区分你正在使用的 vLLM 版本。此时,你可以设置环境变量 VLLM_VERSION 来指定你正在使用的 vLLM 版本,然后针对该版本(例如 v0.9.n)的补丁就应该能正常工作了。