Skip to content

sycl: bound in-flight expert matmuls in mul_mat_id (fix MoE OUT_OF_RESOURCES on Intel iGPU) - #24635

Closed
mayerwin wants to merge 1 commit into
ggml-org:masterfrom
mayerwin:fix-sycl-moe-mul-mat-id-oom
Closed

sycl: bound in-flight expert matmuls in mul_mat_id (fix MoE OUT_OF_RESOURCES on Intel iGPU)#24635
mayerwin wants to merge 1 commit into
ggml-org:masterfrom
mayerwin:fix-sycl-moe-mul-mat-id-oom

Conversation

@mayerwin

@mayerwin mayerwin commented Jun 15, 2026

Copy link
Copy Markdown

Summary

On the SYCL OpenCL backend (Intel Arc iGPU), running MoE expert tensors on the GPU (-ngl 99, no -ot exps=CPU) aborts during multi-token prompt processing:

opencl backend failed with error: 40 (UR_RESULT_ERROR_OUT_OF_RESOURCES)
ggml-sycl.cpp: SYCL error: CHECK_TRY_ERROR(stream->wait())

I hit this on every MoE model I tried with experts on GPU: gemma-4-26b-a4b, qwen3.6-35b-a3b, qwen3-coder-next-80b. This patch makes that configuration run; it is a correctness/availability fix, not a performance optimization.

Root cause

ggml_sycl_mul_mat_id enqueues one matmul per expert (n_as up to hundreds). On a single device ggml_sycl_op_mul_mat does no host wait, and the node-submit loop never waits between graph ops, so the per-expert matmuls accumulate across ops until the next mul_mat_id's start-of-function wait, exceeding the OpenCL UR adapter's in-flight command/event budget.

It is not a single bad kernel: a 128-expert mul_mat_id in isolation (test-backend-ops) does not crash; it only manifests across the full model graph. Anything that throttles submission avoids it (-ub 1, or even heavy debug logging).

Fix

Drain the queue once after the expert loop, gated to the non-Level-Zero backend (no-op on Level Zero):

if (stream->get_backend() != sycl::backend::ext_oneapi_level_zero) {
    SYCL_CHECK(CHECK_TRY_ERROR(stream->wait()));
}

This caps in-flight expert matmuls at a single op's worth. It is numerically inert (it only synchronizes).

Validation (Intel Arc 140T iGPU, OpenCL UR)

No crash, on configs that previously aborted within seconds:

model experts pp512 tg
gemma-4-26b-a4b 128 162 tok/s 14 tok/s
qwen3-coder-next-80b 512 138 tok/s 14 tok/s

test-backend-ops -o MUL_MAT_ID passes. Since the fix only adds a host wait, it cannot change results.

Repro

ONEAPI_DEVICE_SELECTOR=opencl:gpu llama-cli -m gemma-4-26b-a4b-it-Q4_K_M.gguf \
  -ngl 99 -ub 512 -p "<~40-token prompt>" -n 1
# before: UR_RESULT_ERROR_OUT_OF_RESOURCES    after: runs normally

Disclosure: I used an AI coding assistant to help with this. The code change is small; the bulk of the work was diagnosis (reproducing the abort, ruling out the work-group / single-kernel theories, and tracing it to async submission pile-up). The investigation and on-hardware validation are mine.

@mayerwin
mayerwin requested a review from a team as a code owner June 15, 2026 05:20
@github-actions github-actions Bot added ggml changes relating to the ggml tensor library for machine learning SYCL https://en.wikipedia.org/wiki/SYCL - GPU programming language labels Jun 15, 2026
@ggml-gh-bot

ggml-gh-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

Hi @mayerwin, thanks for your contribution!

Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:

  • Multiple open PRs from a new contributor: We limit new contributors (those without a previously merged PR) to 1 open PR at a time. You currently have 2 open PRs.

  • AI-generated content: This project does not accept PRs, descriptions or commit messages that are fully or predominantly AI-generated. If you have used AI to assist you in writing code, please make sure to disclose that explicitly.


Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below.

@arthw

arthw commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@mayerwin
Thank you for your contribution!

I'm interesting in this issue.
SYCL backend is designed to run on Level Zero running time, instead of OpenCL (through it's possible to pass).

  1. Have you tried to run on Level Zero? Why do you choose OpenCL?

  2. I want to reproduce your issue, could you guide me how to do?
    Like OS, iGPU type, LLM (detailed name or download URL), detailed cmd list.

I didn't reproduce this issue by Level Zero on B60 on Ubuntu 24.04.

  1. The method of comparing the performance of -ot exps=CPU and this PR is not correct.
    Because I find add -ot exps=CPU make the performance reduce about 50%.
    The compare should use same parameters.
    Current method can't approve the PR increase the performance.

  2. For the solution in this PR:
    queue.wait() is not needed in most of OP function in fact.
    If we add more it in code, it will decrease the performance.
    I think add one wait() in the function should have same result of add wait() for every 16 loops.
    Could you share the reason of adding wait() and add one for every 16 loops?

Thank you!

…URCES on Intel iGPU

Running MoE expert tensors on the GPU aborts during multi-token prompt
processing on the SYCL OpenCL backend (Intel Arc iGPU) with
UR_RESULT_ERROR_OUT_OF_RESOURCES, surfacing at the stream->wait() in
ggml_sycl_mul_mat_id.

ggml_sycl_mul_mat_id enqueues one matmul per expert (n_as up to hundreds).
ggml_sycl_op_mul_mat does no host wait on a single device and the node-submit
loop never waits between ops, so without a drain the per-expert matmuls
accumulate across ops until the next mul_mat_id's wait, exceeding the OpenCL
UR adapter's in-flight budget. A single 128-expert mul_mat_id in isolation
does not crash; it only manifests across the full model graph.

Drain the queue once after the expert loop, gated to the non-Level-Zero
backend (no-op on Level Zero, the default Intel path). This caps in-flight
expert matmuls at a single op's worth. Validated with no crash on Arc 140T
(OpenCL) for gemma-4-26b-a4b (128 experts) and qwen3-coder-next-80b (512
experts); full-GPU MoE now runs where it previously aborted.
@mayerwin
mayerwin force-pushed the fix-sycl-moe-mul-mat-id-oom branch from c413c1e to 4389502 Compare June 15, 2026 10:30
@mayerwin

mayerwin commented Jun 15, 2026

Copy link
Copy Markdown
Author

Thanks @arthw, this is really helpful. You're right on several points and I've reworked the patch.

Single wait() vs every 16 (your point 4): You're right that one suffices. Each mul_mat_id already drains at its start (the ids memcpy wait), so the backlog that overflows is this call's per-expert matmuls accumulating before the next op drains. A single wait() after the expert loop bounds it to one call's experts. Dropped the counter and the magic number. Validated no-crash on Arc 140T (OpenCL):

model experts pp512 tg
gemma-4-26b-a4b 128 162 14
qwen3-coder-next-80b 512 138 14

Both aborted with UR_RESULT_ERROR_OUT_OF_RESOURCES before. The single wait is also faster than my original every-16 (gemma was 140).

wait() cost (also point 4): agreed, so I gated it to the non-Level-Zero backend, a no-op on L0:

if (stream->get_backend() != sycl::backend::ext_oneapi_level_zero) {
    SYCL_CHECK(CHECK_TRY_ERROR(stream->wait()));
}

Level Zero (points 1 and 2): I'm on OpenCL because ONEAPI_DEVICE_SELECTOR defaulted that way; I did test L0. My build reports GGML_SYCL_SUPPORT_LEVEL_ZERO: no (headers not installed), but that only disables the direct zeMemAlloc path, not the L0 runtime, which is still selectable as level_zero:gpu. On this iGPU (Arc 140T, Arrow Lake-P, Ubuntu 24.04) L0 also fails, but with a different error (a generic SYCL exception from ggml_sycl_op_mul_mat), so there may be a separate L0 issue on this small iGPU. I scoped this PR to the OpenCL OOM and gated the drain off for L0; happy to open a separate issue with the L0 trace. Your B60 (discrete, far more resources) likely hits neither limit.

Repro: Arc 140T iGPU (Arrow Lake-P / Xe2-LPG), Ubuntu 24.04, compute-runtime 24.39.31294; any MoE with experts on GPU:
ONEAPI_DEVICE_SELECTOR=opencl:gpu llama-cli -m gemma-4-26b-a4b-it-Q4_K_M.gguf -ngl 99 -ub 512 -p "<~40-token prompt>" -n 1 (OOM without the patch, runs with it).

Perf table (point 3): you're right, that was apples to oranges (experts-CPU vs experts-GPU). Removed it. This isn't a perf optimization; it makes a config that currently hard-crashes (full-GPU MoE on OpenCL) run at all, so there's no same-config without-flush number.

One note: a reviewer flagged that a single post-loop drain (vs an in-loop chunk) could in theory still overflow for one op with far more experts than tested, on a weaker OpenCL device. The 512-expert pass is reassuring, but I'm glad to add a small in-loop chunk (still gated) if you'd prefer the margin.

@arthw

arthw commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@mayerwin
Got it!
Thank you for your explain!,

GGML_SYCL_SUPPORT_LEVEL_ZERO: no means SYCL will use SYCL API to malloc memory, instead of level zero API. Maybe there is no level-zero dev package is installed in your PC.
Even if GGML_SYCL_SUPPORT_LEVEL_ZERO = no, the code still run on Level-zero, but use SYCL API for memory malloc. Please refer to the explain of GGML_SYCL_SUPPORT_LEVEL_ZERO in SYCL.md.

That means you still can run on Level-Zero even if Level zero API for memory malloc is not supported.

And, I find the UT cases of mul_mat_id is unstable recently on dGPU.
I'm checking it.
After it's fixed, I will check your issue.
Maybe your issue is impacted too.

So the PR will be pending to review.
Hope you understand!

Thank you!

@mayerwin

Copy link
Copy Markdown
Author

Thanks, that matches what I found, and good to confirm the Level Zero runtime is still used regardless of the malloc path.

Makes sense to wait for your mul_mat_id investigation. One possibly-related data point: while validating this on the Arc 140T (OpenCL) I hit an intermittent failure in test-backend-ops -o MUL_MAT_ID on a q6_K case (n_mats=4, n_used=2, m=64, n=16, k=768), NMSE ~0.45, that passed on some runs and failed on others with no code change. Could be the same instability you're seeing on dGPU.

Happy to wait, and glad to re-test this PR and your mul_mat_id fix on the iGPU once it lands.

@arthw

arthw commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@mayerwin
Yes, I meet same random errors.
I will update for new finding.

You could test on Level-Zero running time.

Thank you!

@arthw

arthw commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@mayerwin
I find the PR to involve this issue, refer to: #22862 (comment)

Could you try your test by this cmd?

export GGML_SYCL_ENABLE_VMM=0

Thank you!

@mayerwin

Copy link
Copy Markdown
Author

Update after more testing on the Arc 140T iGPU (OpenCL), and I'll close this.

On GGML_SYCL_ENABLE_VMM (your suggestion): I ran test-backend-ops -o MUL_MAT_ID four times each way. The q6_K case (n_mats=4, n_used=2, m=64, n=16, k=768) fails intermittently with NMSE ~0.43 in about half the runs, at the same rate with VMM on and with VMM=0 (2/4 either way). So the mul_mat_id instability you're tracking shows up on this iGPU too, but it is VMM-independent here; VMM=0 does not fix it, unlike on your dGPU.

On the original OUT_OF_RESOURCES crash: I can no longer reproduce it. With my change reverted, on the same tree, all our MoE models run clean full-GPU under the conditions that originally crashed: qwen3-coder-next-80B (512 experts) and qwen3.6-35b at -c 32768 with repeated long prompts, gemma-4-26b-a4b with repeated 2-image vision, and a 2500-token text prompt, with VMM on or off. I have not changed the library since opening this, so it is not an upstream fix; the original crash looks condition or pressure dependent in a way I cannot currently recreate.

Since I cannot demonstrate the crash or that my change is needed, and it adds a host sync that is pure overhead when the issue is absent, I am closing this. Thanks for the review and the pointers. I will reopen with a solid repro if I hit it again, and I'm glad to test your mul_mat_id fix on the iGPU.

@NeoZhangJianyu

Copy link
Copy Markdown
Contributor

@mayerwin
This PR will fix your issue: #24635

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ggml changes relating to the ggml tensor library for machine learning SYCL https://en.wikipedia.org/wiki/SYCL - GPU programming language

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants