sycl: single-device still requires sync#25741
Conversation
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
|
@hmscider, please take a look at this, the repro steps are in the description. If this is the right fix let me know and I will mark it ready for review or close it if not. |
|
Can confirm garbled output for Gemma 4 12B as well |
NeoZhangJianyu
left a comment
There was a problem hiding this comment.
It's good job!
Thank you!
|
I arrived at similar code from a different (and probably incorrect) hypothesis at #25825. I confirmed that this code alone fixes the problem in Qwen3.5-0.8B. |
Extends the oneDNN SDPA path (PR ggml-org#25222) to handle non-F16 KV caches by dequantizing or converting K/V to dense FP16 on-device before feeding them into the SDPA graph. The fused systolic kernel then runs identically to the native FP16 path. Supported KV types: - Q4_0, Q4_1, Q5_0, Q5_1, Q8_0: to_fp16_sycl / to_fp16_nc_sycl - F32: cont_to_f16_sycl<float> - BF16 and IQ types are excluded (no conversion kernel available) Gate: non-F16 requires K >= 1024 and Q >= 32 (prefill only). F16 KV runs at any length (existing behavior). Also includes the stream sync fix (stream->wait_and_throw() unconditional, PR ggml-org#25741 by @malsbat) and removal of V_is_K_view aliasing (K and V are always dequantized to separate buffers). Co-Authored-By: Claude <noreply@anthropic.com>
|
We hit this same bug in production (Arc Pro B70, Qwen3.6-27B Q4_K, 131k ctx) and root-caused it Root cause: a use-after-return, not missing device synchronization. const sycl::half scale_h = (sycl::half) (1.0f / kq_scale); // stack local
ggml_sycl_pool_alloc<sycl::half> scbuf(ctx.pool(), 1);
stream->memcpy(scbuf.get(), &scale_h, sizeof(sycl::half)); // async, sourced from the stackThe queue is in-order and the dnnl stream wraps the same queue, so every device-side hazard
Direct fix: upload the scale synchronously, once, into a persistent device scalar cached per Deterministic reproducer (unmodified build, GGML_SYCL_F16=ON + GGML_SYCL_DNN=ON): send a single Happy to open the alternative as a follow-up PR (patch is +46/-10: the scale fix, the multi-GPU |
|
Follow-up PR with the root-cause fix is up: #25880 |
|
Thanks @meatposes for the detailed write-up. I only wanted to highlight the issue and suggest a possible fix in this PR. I'm happy to abandon this for your solution which doesn't lose the performance benefit. I'll defer to @arthw for how he'd prefer to handle this. |
…ntion path The scale was uploaded with an async memcpy sourced from a stack local. On the in-order queue that copy is ordered behind the K/V staging kernels; once n_kv is large enough (>= ~26k observed on Arc Pro B70) the staging outlives the host stack frame and the copy reads recycled memory, feeding the SDPA a garbage scale. Output then collapses to a single repeated token and the KV cache is poisoned for the rest of the session. Short contexts win the race by accident, and test-backend-ops caps FLASH_ATTN_EXT at kv=1024, which is why CI never caught it. The previous device_count > 1 wait_and_throw() gate (and reverting it, PR ggml-org#25741) fixes the symptom only by keeping the frame alive across the copy at the cost of a host sync on every FA call. Fix: cache one device scalar per (device, value) -- the scale is constant per model -- and upload it synchronously once. The single-device fast path (no per-call host sync) is then safe: every device-side hazard already serializes on the in-order queue. The multi-GPU conservative wait is kept unchanged. Also: - GGML_SYCL_FA_ONEDNN_MAX_KV env (0 = unlimited): optional n_kv ceiling that routes very long sequences to the native FA kernel. - test-backend-ops: FLASH_ATTN_EXT F16 cases up to kv=65536 (Qwen3.6-27B geometry hsk=hsv=256 GQA 6, and hsk=128 GQA 4), closing the kv=1024 blind spot. Note the race itself needs a live multi-op pipeline to reproduce; single-op runs pass even on broken builds. Verified on Arc Pro B70 (bmg_g31), Qwen3.6-27B Q4_K, -c 131072: output byte-identical at temp 0 to the native FA path through 32k-deep prefill, with prefill depth-flat at 820-840 t/s (vs 340-350 native at 32k depth). Assisted-by: Claude Fable 5
|
Closing, #25880 fixes the issue for me also. |
Overview
Fix garbage output generated on second prompt in multi-turn conversation with model Qwen3-14B-Q4_K_M.
Additional information
This can be reproduced with:
The problematic commit, 32b741c, was identified with help from git bisect.
Requirements