Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
832bfe6
[XPU] Gate FlashAttention-in-graph on oneAPI 2026.0+ runtime support
krisclarkdev Jul 27, 2026
8095a19
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 27, 2026
edf4c39
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 27, 2026
59551dc
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 28, 2026
842bed7
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
6cd9f4d
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
46a0e73
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
82d9d53
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
f3e4c12
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
87a84c9
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 29, 2026
baf82bf
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 30, 2026
b1cba92
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 30, 2026
feb87f5
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 30, 2026
616bb94
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 30, 2026
c507ec6
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 30, 2026
a2a94ce
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 31, 2026
b145aa9
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Jul 31, 2026
096f0cc
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Aug 3, 2026
2506f7a
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Aug 9, 2026
370e39f
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Aug 10, 2026
d45c7e2
Merge branch 'main' into upstream-pr/xpu-fa-in-graph
krisclarkdev Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions tests/utils_/test_torch_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
is_quantized_kv_cache,
set_torch_threads_for_runtime,
startup_omp_num_threads,
supports_xpu_fa_in_graph,
)


Expand Down Expand Up @@ -116,6 +117,25 @@ def child_thread_func():
pytest.fail("Child thread failed to exit properly")


@pytest.mark.parametrize(
("graph_supported", "xpu_ver", "expected"),
[
(True, "20260000", True), # oneAPI 2026.0 -> FA capturable
(True, "20260100", True), # newer 2026.x
(True, "20250302", False), # oneAPI 2025.3 -> scratch not capturable
(True, None, False), # non-XPU torch build
(True, "not-a-number", False), # unparsable -> fail closed
(False, "20260000", False), # torch too old for any XPU graph
],
)
def test_supports_xpu_fa_in_graph(monkeypatch, graph_supported, xpu_ver, expected):
monkeypatch.setattr(
"vllm.utils.torch_utils.supports_xpu_graph", lambda: graph_supported
)
monkeypatch.setattr(torch.version, "xpu", xpu_ver, raising=False)
assert supports_xpu_fa_in_graph() is expected


def test_current_stream_multithread():
if not torch.cuda.is_available():
pytest.skip("CUDA not available")
Expand Down
11 changes: 11 additions & 0 deletions vllm/envs.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@
VLLM_MEMORY_PROFILER_ESTIMATE_CUDAGRAPHS: bool = True
VLLM_NIXL_EP_MAX_NUM_RANKS: int = 32
VLLM_XPU_ENABLE_XPU_GRAPH: bool = False
# When XPU graphs are enabled, clamp full graph modes to PIECEWISE so
# FlashAttention SYCL kernels with work_group_scratch_memory stay outside
# the captured graph. Set to 0 to allow FULL / FULL_AND_PIECEWISE (e.g.
# TRITON_ATTN experiments).
VLLM_XPU_GRAPH_FORCE_PIECEWISE: bool = True
VLLM_XPU_USE_SAMPLER_KERNEL: bool = True
VLLM_LORA_ENABLE_DUAL_STREAM: bool = False
VLLM_GPU_NIC_PCIE_MAPPING: str = ""
Expand Down Expand Up @@ -2040,6 +2045,12 @@ def _resolve_rust_cli_path() -> str | None:
"VLLM_XPU_ENABLE_XPU_GRAPH": lambda: bool(
int(os.getenv("VLLM_XPU_ENABLE_XPU_GRAPH", "0"))
),
# When XPU graphs are on, force cudagraph_mode down to PIECEWISE if the
# configured mode still has full graphs. Default on (safe canary). Set
# VLLM_XPU_GRAPH_FORCE_PIECEWISE=0 to keep FULL / FULL_AND_PIECEWISE.
"VLLM_XPU_GRAPH_FORCE_PIECEWISE": lambda: bool(
int(os.getenv("VLLM_XPU_GRAPH_FORCE_PIECEWISE", "1"))
),
# whether use xpu specific sample kernel
"VLLM_XPU_USE_SAMPLER_KERNEL": lambda: bool(
int(os.getenv("VLLM_XPU_USE_SAMPLER_KERNEL", "1"))
Expand Down
43 changes: 42 additions & 1 deletion vllm/platforms/xpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ def check_and_update_config(cls, vllm_config: VllmConfig) -> None:
compilation_config.compile_sizes = []

# lazy import to avoid circular import
from vllm.utils.torch_utils import supports_xpu_graph
from vllm.utils.torch_utils import (
supports_xpu_fa_in_graph,
supports_xpu_graph,
)

if not supports_xpu_graph():
compilation_config.cudagraph_mode = CUDAGraphMode.NONE
Expand All @@ -300,10 +303,48 @@ def check_and_update_config(cls, vllm_config: VllmConfig) -> None:
"please set VLLM_XPU_ENABLE_XPU_GRAPH=1 to enable it."
)
else:
fa_in_graph_ok = supports_xpu_fa_in_graph()
logger.warning_once(
"XPU Graph support is experimental and currently only supports "
"single-GPU execution."
)
mode = compilation_config.cudagraph_mode
wants_full = mode is not None and mode.has_full_cudagraphs()
if wants_full and envs.VLLM_XPU_GRAPH_FORCE_PIECEWISE:
# Default-on safety clamp (feature 01): keep FlashAttention
# outside the captured graph.
logger.warning_once(
"VLLM_XPU_GRAPH_FORCE_PIECEWISE=1: overriding "
"cudagraph_mode from %s to PIECEWISE so FlashAttention "
"stays outside the XPU Graph. Set "
"VLLM_XPU_GRAPH_FORCE_PIECEWISE=0 to capture FlashAttention "
"in a full graph (needs oneAPI 2026.0+).",
mode.name,
)
compilation_config.cudagraph_mode = CUDAGraphMode.PIECEWISE
elif wants_full and not fa_in_graph_ok:
# Fail-closed: operator opted out of the clamp but the runtime
# cannot capture FA scratch kernels into a SYCL Graph. Capturing
# would raise the work_group_scratch_memory RuntimeError, so
# re-clamp instead of crashing at model warmup.
logger.warning_once(
"VLLM_XPU_GRAPH_FORCE_PIECEWISE=0 requested full graph "
"mode %s, but this runtime cannot capture FlashAttention "
"into a SYCL Graph (needs oneAPI 2026.0+; "
"torch.version.xpu=%s). Falling back to PIECEWISE to avoid "
"the work_group_scratch_memory SYCL Graph error. Upgrade "
"the base image or use TRITON_ATTN for FULL mode.",
mode.name,
getattr(torch.version, "xpu", None),
)
compilation_config.cudagraph_mode = CUDAGraphMode.PIECEWISE
elif wants_full:
logger.info_once(
"FlashAttention-in-graph enabled: capturing full XPU "
"Graph (mode %s) including FlashAttention on oneAPI 2026.0+ "
"runtime.",
mode.name,
)

# Disable fusion passes not yet supported on XPU.
from vllm.config.compilation import CompilationMode
Expand Down
19 changes: 19 additions & 0 deletions vllm/utils/torch_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,25 @@ def supports_xpu_graph() -> bool:
return is_torch_equal_or_newer("2.11.0.dev")


def supports_xpu_fa_in_graph() -> bool:
"""Whether FlashAttention SYCL kernels can be captured into an XPU Graph.

FA kernels use ``sycl_ext_oneapi_work_group_scratch_memory``, which only
became capturable by the SYCL Graph extension on oneAPI 2026.0+ runtimes
(``torch.version.xpu >= 20260000``). On older runtimes capturing FA into a
full graph raises the ``work_group_scratch_memory ... not yet available for
use with the SYCL Graph extension`` RuntimeError, so full graph modes must
keep attention outside the capture (PIECEWISE).
"""
if not supports_xpu_graph():
return False
xpu_ver = getattr(torch.version, "xpu", None)
try:
return xpu_ver is not None and int(xpu_ver) >= 20260000
except (TypeError, ValueError):
return False


# create a library to hold the custom op
vllm_lib = Library("vllm", "FRAGMENT") # noqa

Expand Down
Loading