Skip to content

[Hardware][XPU] Register batch-invariant kernels for XPU - #41934

Merged
yewentao256 merged 53 commits into
vllm-project:mainfrom
tzielinski-habana:xpu_rl
Jul 15, 2026
Merged

yewentao256 merged 53 commits into
vllm-project:mainfrom
tzielinski-habana:xpu_rl

Conversation

@tzielinski-habana

@tzielinski-habana tzielinski-habana commented May 7, 2026

Copy link
Copy Markdown
Contributor

Purpose

This pull request adds partial support for batch invariance on Intel XPU devices. This is a requirement for reinforcement learning on XPU.

Test Plan

Unit tests are modified to cover the registered kernels on XPU.

Test Result

All newly added unit tests pass.

Note

The code was co-developed with GitHub Copilot.

…s for XPU

Co-authored-by: GitHub Copilot
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
@mergify

mergify Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--41934.org.readthedocs.build/en/41934/

@mergify mergify Bot added documentation Improvements or additions to documentation intel-gpu Related to Intel GPU v1 labels May 7, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces experimental support for batch invariance on Intel XPU devices, covering operations such as bmm, log_softmax, softmax, and mean. It includes updated documentation, a new test suite for verifying correctness and invariance on XPU, and the necessary dispatch overrides. The reviewer identified that allow_override=True must be added to the torch.library.Library.impl calls in both the implementation and the test fixtures to prevent potential RuntimeError exceptions caused by conflicting registrations.

Comment thread vllm/model_executor/layers/batch_invariant.py Outdated
Comment thread tests/v1/determinism/test_xpu_batch_invariant.py Outdated
tzielinski-habana and others added 4 commits May 7, 2026 13:17
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Tomasz Zielinski <85164140+tzielinski-habana@users.noreply.github.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
@mergify

mergify Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @tzielinski-habana.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
tzielinski-habana and others added 2 commits May 18, 2026 17:53
Signed-off-by: Tomasz Zielinski <85164140+tzielinski-habana@users.noreply.github.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
tzielinski-habana and others added 7 commits May 19, 2026 14:44
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
@tzielinski-habana
tzielinski-habana marked this pull request as ready for review May 21, 2026 11:48

@yewentao256 yewentao256 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work!

Could you add more context for this PR? Is there a lot of demands from users to realize this in XPU?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we try to reuse current unit test instead creating new one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about it before I marked the PR as ready for review. There are a couple of ways we can go and I wasn't sure which one would be most welcome by the community. Reusing existing tests would introduce some changes around the "skip_unsupported" decorator. I'd have to modify it to include checks for XPU and introduce separate checks for XPU ("skip_if_not_xpu"?) and CUDA ("skip_if_not_cuda"?). The name "skip_if_not_cuda" itself isn't very good, because it checks the condition CUDA and >= Ampere (SM80). All in all, I decided not to go this way, but if you like I can prepare a commit that refactors tests and you can decide which way works better.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, regarding your question about more context and the demand - the context is, we need batch-invariance for reinforcement learning and this PR is basically the first step to enable it. I don't know about the demand for RL, but I asked the team and I'll let you know when I get the answer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yewentao256 please see a preview of what the test refactoring would look like and let me know what you think:
tzielinski-habana#1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have same comment as @yewentao256 , please not creating another tests/v1/determinism/test_xpu_batch_invariant.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update to "skip_unsupported" decorator sounds reasonable to me. @wendyliu235 as well, Her team is working on migrate more cuda to run on XPU, might help to provide suggestion for the generalization work

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll merge my PR with testing improvements: tzielinski-habana#1

Comment on lines +905 to +922
def _register_matmul_overrides(lib, key: str):
"""Register matmul overrides for batch invariance."""
lib.impl("aten::mm", mm_batch_invariant, key)
lib.impl("aten::addmm", addmm_batch_invariant, key)
lib.impl("aten::matmul", matmul_batch_invariant, key)
lib.impl("aten::linear", linear_batch_invariant, key)


def _register_common_overrides(lib, key: str):
"""Register batch-invariant overrides shared across CUDA and XPU."""
lib.impl("aten::_log_softmax", _log_softmax_batch_invariant, key)
lib.impl("aten::softmax", softmax_batch_invariant, key)
lib.impl("aten::_softmax", softmax_batch_invariant, key)
lib.impl("aten::mean.dim", mean_batch_invariant, key)
# torch 2.12+ registers a built-in Triton bmm kernel for CUDA
# (torch._native.ops.bmm_outer_product), so we need allow_override
# to replace it at the dispatcher level.
lib.impl("aten::bmm", bmm_batch_invariant, key, allow_override=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bmm is a kind of matmul?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I assume you're asking this, because I put it with "common overrides" and not "matmul overrides". There are two reasons for this:

  1. bmm_batch_invariant has a dedicated Triton kernel (bmm_kernel) while the ops from matmul overrides all use matmul_kernel_persistent (with a small caveat - matmul_batch_invariant uses matmul_kernel_persistent in 2/3 if/else branches and bmm_kernel in the one remaining branch).
  2. more imporantly, the common overrides are unconditional for both CUDA and XPU, while matmul overrides are only registered for cuda if this condition holds: if current_platform.is_device_capability_family(80). So we need to keep these groups separate. If you prefer some other names for these functions, can you give me some suggestions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the refactor here, let's keep the change minimal in this file. we may use key = "cuda" or "xpu" outside, then

_batch_invariant_LIB.impl("aten::softmax", softmax_batch_invariant, key) directly instead of this function warpper

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I significantly reduced the scope of this PR. Got rid of the refactor and removed the common ops test. I'm also skipping matmul and linear registrations for now, because they require more work. I plan to add them in another PR later.

Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
@mergify mergify Bot removed the needs-rebase label Jun 24, 2026
@mergify

mergify Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Hi @tzielinski-habana, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

Comment thread tests/v1/determinism/utils.py Outdated
Comment on lines +54 to +61
XPU_BACKENDS: list[str] = [
"TRITON_ATTN",
]


def skip_unsupported_xpu_backends(backend: str):
if current_platform.is_xpu() and backend not in XPU_BACKENDS:
pytest.skip(f"Backend {backend} not verified for batch invariance on XPU")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently all devices and backends are quite complicated, please organize them all together, design with a cleaner version.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will do

Comment on lines +897 to +901
def enable_batch_invariant_mode():
if not (current_platform.is_cuda() or current_platform.is_xpu()):
raise NotImplementedError(
"Batch invariance is only supported on CUDA and XPU platforms, "
f"got {current_platform.device_name}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if Rocm is enabled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have access to ROCm to check. I will remove this condition

Comment on lines +172 to +175
# Not all batch-invariant kernels are registered on XPU yet
# (e.g. attention, custom ops), so e2e determinism is not guaranteed.
if current_platform.is_xpu():
pytest.xfail("Not all batch-invariant kernels registered on XPU yet")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e2e determinism is not guaranteed

We want it is guaranteed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but that means the PR needs to be much larger. I wanted to register a subset of the kernels first and add the other ones later.

tzielinski-habana and others added 2 commits July 6, 2026 10:35
Signed-off-by: tzielinski-habana <tomasz.zielinski@intel.com>
Comment thread tests/v1/determinism/utils.py

@yewentao256 yewentao256 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Looks much better, thanks!

Comment thread tests/v1/determinism/test_batch_invariance.py Outdated
Comment thread tests/v1/determinism/test_batch_invariance.py Outdated

@yewentao256 yewentao256 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All E2E tests are xfail

# Not all batch-invariant kernels are registered on XPU yet
    # (e.g. attention, custom ops), so e2e determinism is not guaranteed.
    if current_platform.is_xpu():
        pytest.xfail("Not all batch-invariant kernels registered on XPU yet")

Are we sure this is what we want? I hope we can make sure at least one dense e2e like Qwen 3 could pass

@tzielinski-habana

Copy link
Copy Markdown
Contributor Author

All E2E tests are xfail

# Not all batch-invariant kernels are registered on XPU yet
    # (e.g. attention, custom ops), so e2e determinism is not guaranteed.
    if current_platform.is_xpu():
        pytest.xfail("Not all batch-invariant kernels registered on XPU yet")

Are we sure this is what we want? I hope we can make sure at least one dense e2e like Qwen 3 could pass

@yewentao256 e2e tests are xfailed, because this PR is only the first step, out of two, to enable batch invariance on XPU. It's missing matmul and linear kernels registrations, because they are more problematic and require more code and a custom matmul kernel with tensor descriptors. I'm sure there will be quite a few review comments for the new code.

I wanted to break it down for two reasons:

  1. Two smaller PRs are easier to understand and review
  2. If something unexpected breaks, we can have a more granular bisection

I had to rebase the branch a lot of times to make CI pass, because it is extremely unstable for some reason - every other time I got some interrupts/infrastructure issues. Now I see CI has finally passed, so if you're ok with that, I would love to merge this PR and then I'm going to submit the missing kernels in the next one. If not, I can expand this PR to cover end to end scenarios, but I think the more granular approach is better and we can deliver part of the functionality sooner.

@yewentao256 yewentao256 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the work!

@yewentao256
yewentao256 merged commit 61141ed into vllm-project:main Jul 15, 2026
93 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation intel-gpu Related to Intel GPU ready ONLY add when PR is ready to merge/full CI is needed v1 verified Run pre-commit for new contributors without triggering other tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants