[XPU] Add VLLM_XPU_DEVICE_OFFSET to place a worker on a non-zero card without masking - #53076
Draft
adobrzyn wants to merge 2 commits into
Draft
[XPU] Add VLLM_XPU_DEVICE_OFFSET to place a worker on a non-zero card without masking#53076adobrzyn wants to merge 2 commits into
adobrzyn wants to merge 2 commits into
Conversation
On XPU a worker binds xpu:{local_rank}, so putting a single-GPU vLLM
instance on a non-zero card today requires narrowing visibility with
ZE_AFFINITY_MASK. That masking makes each process see only one device,
which breaks oneCCL/XCCL collectives spanning separate processes (oneCCL
requires every communicator device UUID to be visible per process), so
e.g. RL weight sync between a trainer on xpu:0 and a standalone vLLM
server on xpu:1 hangs at the first collective.
Add VLLM_XPU_DEVICE_OFFSET (default 0): the physical device index is
local_rank + offset, applied consistently to the device and to the
init memory query, while all cards stay visible. Setting the offset to
1 places a single-GPU server on xpu:1 with both cards visible, so the
cross-process XCCL collective builds its topology and runs.
Signed-off-by: Agata Dobrzyniewicz <agata.dobrzyniewicz@intel.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a "Selecting a specific XPU device" subsection describing how to pin a worker to a non-zero card without ZE_AFFINITY_MASK, and why that is preferred when a cross-process XCCL collective is involved. Signed-off-by: Agata Dobrzyniewicz <agata.dobrzyniewicz@intel.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Documentation preview: https://vllm--53076.org.readthedocs.build/en/53076/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
On XPU a worker always binds
xpu:{local_rank}, so placing a single-GPU vLLMinstance on a non-zero card currently requires narrowing device visibility
with
ZE_AFFINITY_MASK. That masking makes each process see only one device,which breaks oneCCL/XCCL collectives that span separate processes: oneCCL
requires every device UUID in a communicator to be visible within each
participating process (
comm_dev_uuidsmust be a sub-vector ofnode_dev_uuids). With a per-process mask each process sees a single UUID whilethe collective spans two, the check fails, and the collective hangs.
Concrete case: RL post-training with a trainer on
xpu:0and a standalonevllm serveonxpu:1on the same host. The trainer↔server weight-sync XCCLgroup hangs at the first broadcast under masking, and the only workaround so far
has been to fall back to gloo (host-staged, ~15× slower for multi-GB weight
transfers).
Change
Add
VLLM_XPU_DEVICE_OFFSET(int, default0). The physical device indexbecomes
local_rank + VLLM_XPU_DEVICE_OFFSET, applied consistently toself.deviceand to the init-timeget_device_propertiesquery, while allcards remain visible (no
ZE_AFFINITY_MASK).VLLM_XPU_DEVICE_OFFSET=1placesa single-GPU server on
xpu:1with both cards visible, so a cross-process XCCLcollective can build its 2-device topology and run.
Default
0is a no-op, so existing single- and multi-card behavior is unchanged.Why this is not a duplicate of #46226
#46226 ("[XPU] Set per-worker
ZE_AFFINITY_MASKfor workers") touches the samefiles but takes the opposite approach: it isolates workers by masking so
each worker sees exactly one card. That is useful for per-worker memory
profiling / KV sizing, but it is precisely what breaks cross-process oneCCL/XCCL
(above). This PR isolates by device index while keeping every card visible,
which is required for cross-process collectives such as RL weight sync. The two
are complementary (offset defaults to
0, no mask), but they solve differentproblems and should not be conflated.
Test plan and results
Validated end-to-end on 2× Intel Arc Pro B60 (torch 2.13.0+xpu, oneCCL 2022.0.0,
Level-Zero 1.32.0), GRPO (TRL) with a standalone
vllm serve:VLLM_XPU_DEVICE_OFFSET=1→ engine came up onxpu:1with both cards visible; trainer stayed on
xpu:0.hung at the first collective under
ZE_AFFINITY_MASK); the fatal oneCCL... is not sub-vector of node_dev_uuids ... narrow device affinity maskmessage no longer appears (0 occurrences).
~1.7× faster than the gloo fallback in the same setup.
ProcessGroupXCCLbroadcast reproducer confirms the rootcause independently: masked (1 visible card/process) → hang; unmasked with
index selection → pass.
Static checks:
python -m py_compile vllm/envs.py vllm/v1/worker/xpu_worker.py # OK pre-commit run --files vllm/envs.py vllm/v1/worker/xpu_worker.pyModel evaluation: not applicable — this only changes which physical XPU a
worker binds to; it does not alter model outputs, numerics, or accuracy.
Notes
AI assistance (Claude Code) was used to draft this change; the submitter
reviewed every changed line and ran the validation above on real hardware.
Draft: opening for early feedback on the approach and its relationship to #46226.