跳到內容

vLLM 輪式夜間構建

vLLM 在 https://wheels.vllm.ai 維護一個每個提交的輪式檔案倉庫(通常稱為“夜間構建”),該倉庫提供自 v0.5.3 以來 main 分支上每個提交的預構建輪式檔案。本文件解釋了夜間構建輪式檔案索引機制的工作原理。

CI 上的構建和上傳流程

輪式構建

輪式檔案在 PR 合併到 main 分支後,在 Release 管道(.buildkite/release-pipeline.yaml)中構建,幷包含多個變體。

  • 後端變體cpucuXXX(例如 cu129cu130)。
  • 架構變體x86_64aarch64

每個構建步驟

  1. 在 Docker 容器中構建輪式檔案。
  2. 重新命名輪式檔名,使用正確的 manylinux 標籤(當前為 manylinux_2_31)以符合 PEP 600。
  3. 將輪式檔案上傳到 S3 儲存桶 vllm-wheels 下的 /{commit_hash}/ 目錄。

索引生成

上傳每個輪式檔案後,.buildkite/scripts/upload-wheels.sh 指令碼會

  1. 列出 S3 中提交目錄下的所有現有輪式檔案
  2. 使用 .buildkite/scripts/generate-nightly-index.py 生成索引
    • 解析輪式檔名以提取元資料(版本、變體、平臺標籤)。
    • 建立 HTML 索引檔案(index.html),以相容 PyPI。
    • 生成機器可讀的 metadata.json 檔案。
  3. 將索引上傳到多個位置(覆蓋現有索引)。
    • /{commit_hash}/ - 始終上傳,用於特定提交的訪問。
    • /nightly/ - 僅用於 main 分支上的提交(非 PR)。
    • /{version}/ - 僅用於釋出輪式檔案(版本號中不包含 dev)。

處理併發構建

索引生成指令碼可以透過在生成索引前始終列出提交目錄中的所有輪式檔案來處理併發構建的多個變體,從而避免競態條件。

目錄結構

S3 儲存桶結構遵循此模式:

s3://vllm-wheels/
├── {commit_hash}/              # Commit-specific wheels and indices
│   ├── vllm-*.whl              # All wheel files
│   ├── index.html              # Project list (default variant)
│   ├── vllm/
│   │   ├── index.html          # Package index (default variant)
│   │   └── metadata.json       # Metadata (default variant)
│   ├── cu129/                  # Variant subdirectory
│   │   ├── index.html          # Project list (cu129 variant)
│   │   └── vllm/
│   │       ├── index.html      # Package index (cu129 variant)
│   │       └── metadata.json   # Metadata (cu129 variant)
│   ├── cu130/                  # Variant subdirectory
│   ├── cpu/                    # Variant subdirectory
│   └── .../                    # More variant subdirectories
├── nightly/                    # Latest main branch wheels (mirror of latest commit)
└── {version}/                  # Release version indices (e.g., 0.11.2)

所有構建的輪式檔案都儲存在 /{commit_hash}/ 中,而不同的索引被生成並引用它們。這避免了輪式檔案重複。

例如,您可以透過以下 URL 指定來使用不同的索引:

  • https://wheels.vllm.ai/nightly/cu130 用於構建的最新 main 分支 CUDA 13.0 輪式檔案。
  • https://wheels.vllm.ai/{commit_hash} 用於特定提交構建的輪式檔案(預設變體)。
  • https://wheels.vllm.ai/0.12.0/cpu 用於 0.12.0 釋出版 CPU 變體的輪式檔案。

請注意,並非所有變體都存在於每個提交中。可用變體可能會隨時間變化,例如將 cu130 更改為 cu131。

變體組織

索引按變體組織:

  • 預設變體:沒有變體字尾的輪式檔案(即使用當前的 VLLM_MAIN_CUDA_VERSION 構建的)放置在根目錄。
  • 變體子目錄:帶有變體字尾的輪式檔案(例如 +cu130.cpu)組織在子目錄中。
  • 預設別名:預設變體可以有一個別名(例如,當前為 cu129),以保持一致性和便利性。

變體從輪式檔名中提取(如檔名約定中所述)。

  • 變體編碼在本地版本識別符號中(例如 +cu129dev<N>+g<hash>.cu130)。
  • 示例
    • vllm-0.11.2.dev278+gdbc3d9991-cp38-abi3-manylinux1_x86_64.whl → 預設變體
    • vllm-0.10.2rc2+cu129-cp38-abi3-manylinux2014_aarch64.whlcu129 變體
    • vllm-0.11.1rc8.dev14+gaa384b3c0.cu130-cp38-abi3-manylinux1_x86_64.whlcu130 變體

索引生成詳情

generate-nightly-index.py 指令碼執行以下操作:

  1. 使用正則表示式解析輪式檔名以提取:
    • 包名
    • 版本(已提取變體)
    • Python 標籤、ABI 標籤、平臺標籤
    • 構建標籤(如果存在)
  2. 按變體分組輪式檔案,然後按包名分組。
    • 目前只構建 vllm,但該結構支援未來構建多個包。
  3. 生成 HTML 索引(符合簡單倉庫 API)。
    • 頂層 index.html:列出所有包和變體子目錄。
    • 包級別 index.html:列出該包的所有輪式檔案。
    • 使用相對路徑到輪式檔案,以提高可移植性。
  4. 生成 metadata.json:
    • 機器可讀的 JSON,包含所有輪式檔案元資料。
    • 包含 path 欄位,其中包含 URL 編碼的輪式檔案相對路徑。
    • setup.py 在純 Python 構建期間定位相容的預編譯輪式檔案時使用。

AWS 服務特殊處理

輪式檔案和索引直接儲存在 AWS S3 上,我們使用 AWS CloudFront 作為 S3 儲存桶前面的 CDN。

由於 S3 不提供正確的目錄列表功能,為了支援 PyPI 相容的簡單倉庫 API 行為,我們部署了一個 CloudFront Function,它會:

  • 將任何不以 / 結尾且看起來不像檔案的 URL(即最後一個路徑段不包含點 .)重定向到具有尾部 / 的相同 URL。
  • /index.html 追加到任何以 / 結尾的 URL。

例如,以下請求將被處理為:

  • /nightly/nightly/index.html
  • /nightly/cu130//nightly/cu130/index.html
  • /nightly/index.html/nightly/vllm.whl → 不變

AWS S3 檔名轉義

S3 會根據其命名規則在上傳時自動轉義檔名。對 vllm 的直接影響是檔名中的 + 將被轉換為 %2B。我們在索引生成指令碼中特別注意在生成 HTML 索引和 JSON 元資料時正確轉義檔名,以確保 URL 正確且可直接使用。

setup.py 中使用預編譯的輪式檔案

當使用 VLLM_USE_PRECOMPILED=1 安裝 vLLM 時,setup.py 指令碼會:

  1. 透過 precompiled_wheel_utils.determine_wheel_url() **確定輪式檔案位置**。
    • 環境變數 VLLM_PRECOMPILED_WHEEL_LOCATION(使用者指定的 URL/路徑)始終具有最高優先順序,並跳過所有其他步驟。
    • 透過 VLLM_MAIN_CUDA_VERSION 確定變體(可以透過環境變數 VLLM_PRECOMPILED_WHEEL_VARIANT 覆蓋);還將嘗試使用預設變體作為後備。
    • 確定此分支的 *基本提交*(稍後解釋)(可以透過環境變數 VLLM_PRECOMPILED_WHEEL_COMMIT 覆蓋)。
  2. https://wheels.vllm.ai/{commit}/vllm/metadata.json(預設變體)或 https://wheels.vllm.ai/{commit}/{variant}/vllm/metadata.json(特定變體)**獲取元資料**。
  3. **根據以下條件選擇相容的輪式檔案**:
    • 包名(vllm
    • 平臺標籤(架構匹配)
  4. **下載並提取**預編譯的二進位制檔案:
    • C++ 擴充套件模組(.so 檔案)
    • Flash Attention Python 模組
    • Triton 核心 Python 檔案
  5. **修補 package_data** 以包含安裝中的提取檔案。

什麼是基本提交?

基本提交是透過查詢當前分支與上游 main 分支之間的合併基礎來確定的,以確保原始碼與預編譯二進位制檔案之間的相容性。

注意:在使用預編譯輪式檔案之前,使用者有責任確保沒有原生代碼(例如 C++ 或 CUDA)的更改。

實現檔案

夜間構建輪式檔案機制中涉及的關鍵檔案:

  • .buildkite/release-pipeline.yaml:構建輪式檔案的 CI 管道。
  • .buildkite/scripts/upload-wheels.sh:上傳輪式檔案並生成索引的指令碼。
  • .buildkite/scripts/generate-nightly-index.py:生成 PyPI 相容索引的 Python 指令碼。
  • setup.py:包含用於獲取和使用預編譯輪式檔案的 precompiled_wheel_utils 類。