[Build] Fix CUDA arch detection producing kernel-less builds on SM121 (#49904)
Ayushman Singh committed
Jul 28, 2026 at 01:01 UTC
74587939b17b4eb3ba281ec9ca43f93aa230a3cb
3 files changed
+40
-9
CMakeLists.txt
+9
-4
@@ -219,10 +219,8 @@ if(VLLM_GPU_LANG STREQUAL "CUDA")
219
# the set of architectures we want to compile for and remove the from the
220
# CMAKE_CUDA_FLAGS so that they are not applied globally.
221
#
222
- # `+PTX` in TORCH_CUDA_ARCH_LIST is not preserved here. It is emitted by torch
223
- # as `code=compute_*`, while extract_unique_cuda_archs_ascending() records only
224
- # `arch=compute_*`. If a kernel really needs PTX, add `+PTX` to that kernel's
225
- # component-specific arch list below.
222
+ # `+PTX` in TORCH_CUDA_ARCH_LIST is not preserved here. If a kernel really
223
+ # needs PTX, add `+PTX` to that kernel's component-specific arch list below.
224
#
225
clear_cuda_arches(CUDA_ARCH_FLAGS)
226
extract_unique_cuda_archs_ascending(CUDA_ARCHS "${CUDA_ARCH_FLAGS}")
@@ -232,6 +230,13 @@ if(VLLM_GPU_LANG STREQUAL "CUDA")
230
cuda_archs_loose_intersection(CUDA_ARCHS
231
"${CUDA_SUPPORTED_ARCHS}" "${CUDA_ARCHS}")
232
message(STATUS "CUDA supported target architectures: ${CUDA_ARCHS}")
233
+ if(NOT CUDA_ARCHS)
234
+ message(FATAL_ERROR
235
+ "No supported CUDA architectures; the build would produce a binary "
236
+ "with no usable kernels. Detected gencode flags: ${CUDA_ARCH_FLAGS}; "
237
+ "supported: ${CUDA_SUPPORTED_ARCHS}. "
238
+ "Set TORCH_CUDA_ARCH_LIST for your GPU (e.g. 12.0).")
239
+ endif()
240
else()
241
#
242
# For other GPU targets override the GPU architectures detected by cmake/torch
cmake/utils.cmake
+6
-5
@@ -241,14 +241,15 @@ endmacro()
241
# `<major>.<minor>`, dedupes them and then sorts them in ascending order and
242
# stores them in `OUT_ARCHES`.
243
#
244
-# Example:
245
-# CUDA_ARCH_FLAGS="-gencode arch=compute_75,code=sm_75;...;-gencode arch=compute_90a,code=sm_90a"
246
-# extract_unique_cuda_archs_ascending(OUT_ARCHES CUDA_ARCH_FLAGS)
247
-# OUT_ARCHES="7.5;...;9.0"
244
+# Prefer `code=sm_*`; fall back to `arch=compute_*` for PTX-only flags.
245
+# This handles mismatches such as `arch=compute_20,code=sm_121`.
246
function(extract_unique_cuda_archs_ascending OUT_ARCHES CUDA_ARCH_FLAGS)
247
set(_CUDA_ARCHES)
248
foreach(_ARCH ${CUDA_ARCH_FLAGS})
251
- string(REGEX MATCH "arch=compute_\([0-9]+[af]?\)" _COMPUTE ${_ARCH})
249
+ string(REGEX MATCH "code=sm_\([0-9]+[af]?\)" _COMPUTE ${_ARCH})
250
+ if (NOT _COMPUTE)
251
+ string(REGEX MATCH "arch=compute_\([0-9]+[af]?\)" _COMPUTE ${_ARCH})
252
+ endif()
253
if (_COMPUTE)
254
set(_COMPUTE ${CMAKE_MATCH_1})
255
endif()
tests/test_cmake_utils.py
+25
@@ -21,3 +21,28 @@ endif()
21
)
22
23
subprocess.run(["cmake", "-P", script], check=True)
24
+
25
+
26
+def test_extract_archs_prefers_sass_target_over_corrupted_virtual_arch(
27
+ tmp_path: Path,
28
+):
29
+ """torch's autodetection can emit a bogus arch=compute_* half (e.g.
30
+ capability 12.1 corrupted to arch=compute_20,code=sm_121); the SASS
31
+ target must win, while PTX-only entries keep the virtual arch."""
32
+ repo_root = Path(__file__).parents[1]
33
+ script = tmp_path / "test_extract_archs.cmake"
34
+ script.write_text(
35
+ f"""
36
+cmake_minimum_required(VERSION 3.26)
37
+include("{repo_root / "cmake" / "utils.cmake"}")
38
+extract_unique_cuda_archs_ascending(actual
39
+ "-gencode arch=compute_20,code=sm_121;\
40
+-gencode arch=compute_80,code=sm_80;\
41
+-gencode arch=compute_80,code=compute_80")
42
+if(NOT "${{actual}}" STREQUAL "8.0;12.1")
43
+ message(FATAL_ERROR "Expected '8.0;12.1', got '${{actual}}'")
44
+endif()
45
+"""
46
+ )
47
+
48
+ subprocess.run(["cmake", "-P", script], check=True)