[Bugfix][CPU][RISC-V] Fix VLEN detection for RVV attention path (#47532)
Signed-off-by: liutong <liutong@iscas.ac.cn> Co-authored-by: Claude <noreply@anthropic.com>
LiuTong committed
Jul 6, 2026 at 13:58 UTC
16f81109357041f844aebfd4cb35e95600e2dda9
3 files changed
+26
-18
cmake/cpu_extension.cmake
+11
-1
@@ -178,7 +178,10 @@ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64")
178
# Override with -DVLLM_RVV_VLEN=128 or -DVLLM_RVV_VLEN=256 for RVV.
179
if(NOT DEFINED VLLM_RVV_VLEN)
180
# Auto-detect: find the largest zvl<N>b in /proc/cpuinfo isa line.
181
- if(EXISTS /proc/cpuinfo)
181
+ # Skip when cross-compiling — /proc/cpuinfo describes the build host.
182
+ if(CMAKE_CROSSCOMPILING)
183
+ message(STATUS "Cross-compiling: skipping VLEN auto-detection from /proc/cpuinfo")
184
+ elseif(EXISTS /proc/cpuinfo)
185
file(READ /proc/cpuinfo _cpuinfo)
186
set(_best 0)
187
foreach(_n IN ITEMS 128 256 512 1024)
@@ -186,6 +189,13 @@ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64")
189
set(_best ${_n})
190
endif()
191
endforeach()
192
+ # Only VLEN=128 and VLEN=256 are supported by the RVV kernels.
193
+ if(_best GREATER 256)
194
+ message(WARNING
195
+ "Detected VLEN=${_best} but only 128/256 are supported; "
196
+ "clamping to 256")
197
+ set(_best 256)
198
+ endif()
199
if(_best GREATER 0)
200
set(VLLM_RVV_VLEN ${_best})
201
endif()
csrc/cpu/cpu_attn.cpp
+2
-1
@@ -13,7 +13,8 @@ static inline cpu_attention::Fp8KVCacheDataType parse_fp8_kv_dtype(
13
14
bool cpu_attn_has_isa(const std::string& isa) {
15
if (isa == "rvv") {
16
-#if defined(__riscv) && defined(__riscv_v_min_vlen) && __riscv_v_min_vlen == 128
16
+#if defined(__riscv) && defined(__riscv_v_min_vlen) && \
17
+ (__riscv_v_min_vlen == 128 || __riscv_v_min_vlen == 256)
18
return true;
19
#else
20
return false;
vllm/v1/attention/backends/cpu_attn.py
+13
-16
@@ -437,27 +437,24 @@ def _riscv_supports_rvv() -> bool:
437
The RVV path is compiled whenever __riscv_v_min_vlen is defined, so
438
we check that at least one supported zvl<N>b is advertised.
439
"""
440
- try:
441
- with open("/proc/cpuinfo") as f:
442
- cpuinfo = f.read()
443
- except OSError:
444
- return False
445
- # If VLEN >= 512 is detected, the RVV kernel was not compiled.
446
- if any(f"zvl{n}b" in cpuinfo for n in (512, 1024)):
447
- return False
448
-
449
- # zvl128b or zvl256b explicitly advertised -> RVV kernel available.
450
- if any(f"zvl{n}b" in cpuinfo for n in (128, 256)):
451
- return True
452
-
453
- # No zvl<N>b flag at all (e.g. some hardware reports zve* without
454
- # a VLEN hint). Delegate to the C++ compile-time check instead.
440
+ # The C++ compile-time check is the ground truth: it knows which
441
+ # VLEN the binary was actually compiled for. The cpuinfo check
442
+ # below is only a fast-path shortcut.
443
try:
444
import torch
445
458
- return torch.ops._C.cpu_attn_has_isa("rvv")
446
+ if torch.ops._C.cpu_attn_has_isa("rvv"):
447
+ return True
448
except Exception:
449
+ pass
450
+
451
+ # Fallback: check /proc/cpuinfo for zvl128b/zvl256b.
452
+ try:
453
+ with open("/proc/cpuinfo") as f:
454
+ cpuinfo = f.read()
455
+ except OSError:
456
return False
457
+ return any(f"zvl{n}b" in cpuinfo for n in (128, 256))
458
459
460
def _get_attn_isa(