diff --git a/CMakeLists.txt b/CMakeLists.txt index e261bf1ac8..64de3baa9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,7 +222,8 @@ if(VLLM_GPU_LANG STREQUAL "CUDA") # `+PTX` in TORCH_CUDA_ARCH_LIST is not preserved here. If a kernel really # needs PTX, add `+PTX` to that kernel's component-specific arch list below. # - clear_cuda_arches(CUDA_ARCH_FLAGS) + clear_cuda_gencode_flags(CUDA_ARCH_FLAGS) + warn_if_ptx_arch_requested("${CUDA_ARCH_FLAGS}") extract_unique_cuda_archs_ascending(CUDA_ARCHS "${CUDA_ARCH_FLAGS}") message(STATUS "CUDA target architectures: ${CUDA_ARCHS}") # Filter the target architectures by the supported supported archs diff --git a/cmake/utils.cmake b/cmake/utils.cmake index bbae89c1f5..6ded936213 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -220,11 +220,11 @@ endmacro() # # Example: # CMAKE_CUDA_FLAGS="-Wall -gencode arch=compute_70,code=sm_70 -gencode arch=compute_75,code=sm_75" -# clear_cuda_arches(CUDA_ARCH_FLAGS) +# clear_cuda_gencode_flags(CUDA_ARCH_FLAGS) # CUDA_ARCH_FLAGS="-gencode arch=compute_70,code=sm_70;-gencode arch=compute_75,code=sm_75" # CMAKE_CUDA_FLAGS="-Wall" # -macro(clear_cuda_arches CUDA_ARCH_FLAGS) +macro(clear_cuda_gencode_flags CUDA_ARCH_FLAGS) # Extract all `-gencode` flags from `CMAKE_CUDA_FLAGS` string(REGEX MATCHALL "-gencode arch=[^ ]+" CUDA_ARCH_FLAGS ${CMAKE_CUDA_FLAGS}) @@ -235,6 +235,26 @@ macro(clear_cuda_arches CUDA_ARCH_FLAGS) ${CMAKE_CUDA_FLAGS}) endmacro() +# +# Warn when a caller requested PTX code generation through global CUDA arch +# flags. vLLM removes those flags and reapplies per-source gencode flags, so the +# user's global PTX request will not be preserved. +# +function(warn_if_ptx_arch_requested CUDA_ARCH_FLAGS) + foreach(_ARCH_FLAG ${CUDA_ARCH_FLAGS}) + if(_ARCH_FLAG MATCHES "code=.*compute_[0-9]+[af]?") + message(WARNING + "PTX code generation requested in CUDA architecture flags " + "(${_ARCH_FLAG}), but vLLM does not preserve global PTX requests " + "when normalizing per-source CUDA architectures. Remove '+PTX' from " + "TORCH_CUDA_ARCH_LIST or rely on vLLM's built-in per-kernel PTX " + "selection.") + return() + endif() + endforeach() +endfunction() + + # # Extract unique CUDA architectures from a list of compute capabilities codes in # the form `[]`, convert them to the form sort diff --git a/docs/getting_started/installation/gpu.cuda.inc.md b/docs/getting_started/installation/gpu.cuda.inc.md index 4b82178a4d..a417bf4af7 100644 --- a/docs/getting_started/installation/gpu.cuda.inc.md +++ b/docs/getting_started/installation/gpu.cuda.inc.md @@ -156,6 +156,9 @@ cd vllm uv pip install -e . --torch-backend=auto ``` +!!! note "CUDA Architecture & PTX Flags" + vLLM normalizes CUDA architectures on a per-source basis to optimize build times and wheel sizes. Global `+PTX` requests in `TORCH_CUDA_ARCH_LIST` (e.g., `TORCH_CUDA_ARCH_LIST="8.0+PTX"`) are ignored for general extension targets; vLLM generates PTX only for specific internal kernels that require it. + !!! tip Building from source requires a lot of compilation. If you are building from source repeatedly, it's more efficient to cache the compilation results. diff --git a/tests/test_cmake_utils.py b/tests/test_cmake_utils.py index d0673bc462..dd0c6261d3 100644 --- a/tests/test_cmake_utils.py +++ b/tests/test_cmake_utils.py @@ -1,10 +1,22 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project +import shutil import subprocess +import sys from pathlib import Path +def _get_cmake_bin() -> str: + cmake = shutil.which("cmake") + if cmake: + return cmake + venv_cmake = Path(sys.executable).parent / "cmake" + if venv_cmake.is_file(): + return str(venv_cmake) + return "cmake" + + def test_exact_family_arch_precedes_generic_family_fallback(tmp_path: Path): repo_root = Path(__file__).parents[1] script = tmp_path / "test_cuda_archs.cmake" @@ -20,7 +32,7 @@ endif() """ ) - subprocess.run(["cmake", "-P", script], check=True) + subprocess.run([_get_cmake_bin(), "-P", script], check=True) def test_extract_archs_prefers_sass_target_over_corrupted_virtual_arch( @@ -45,4 +57,26 @@ endif() """ ) - subprocess.run(["cmake", "-P", script], check=True) + subprocess.run([_get_cmake_bin(), "-P", script], check=True) + + +def test_clear_cuda_gencode_flags(tmp_path: Path): + repo_root = Path(__file__).parents[1] + script = tmp_path / "test_clear_flags.cmake" + script.write_text( + f""" +cmake_minimum_required(VERSION 3.26) +include("{repo_root / "cmake" / "utils.cmake"}") +set(CMAKE_CUDA_FLAGS "-Wall -gencode arch=compute_80,code=sm_80") +clear_cuda_gencode_flags(CUDA_ARCH_FLAGS) +if(NOT "${{CMAKE_CUDA_FLAGS}}" STREQUAL "-Wall ") + message(FATAL_ERROR "Expected '-Wall ', got '${{CMAKE_CUDA_FLAGS}}'") +endif() +if(NOT "${{CUDA_ARCH_FLAGS}}" STREQUAL "-gencode arch=compute_80,code=sm_80") + message(FATAL_ERROR "Expected '-gencode arch=compute_80,code=sm_80', " + "got '${{CUDA_ARCH_FLAGS}}'") +endif() +""" + ) + + subprocess.run([_get_cmake_bin(), "-P", script], check=True)