Skip to content

Sycl --split-mode tensor#24152

Merged
ggerganov merged 5 commits into
ggml-org:masterfrom
Spruill-1:master
Jun 25, 2026
Merged

Sycl --split-mode tensor#24152
ggerganov merged 5 commits into
ggml-org:masterfrom
Spruill-1:master

Conversation

@Spruill-1

Copy link
Copy Markdown
Contributor

Overview

Adds the comm_init/comm_free/comm_allreduce_tensor trio that the meta-backend wants via get_proc_address to enable backend-specific all-reduce, mirroring the pattern used by ggml-cuda.cu.

For N=2 (dual-GPUs) implements a degenerate ring allreduce with two size-branched paths to mirror CUDA NCCL allreduce:

  • Small (N< 32k): FP32 direct memcpy + per-device ADD kernel chained via depends_on(memcpy_event). 4 submissions/call.

  • Large (N>= 32k): BF16-compressed. Each device compresses FP32 -> BF16 locally, cross-device memcpys to the peer, then decompresses + adds into the local FP32 partial. 6 SYCL submissions/call but PCIe bytes halved. Wins overall for larger dense models.

Storage: A single persistent uint8_t buffer per device, 4 * N bytes (matches both path layouts: FP32 N floats; BF16 outbox+inbox = 2 * N uint16_t each). Single alloc+free per device keeps the SYCL pool's strict-LIFO invariant.

Initial impl handles N=2 FP32 contiguous tensors. Other cases return false, causing the meta-backend to use its generic butterfly fallback. This should be easy to extend to N>2, but I don't have the hardware.

Measured on dual Intel Arc Pro B70 (NEO 26.05.x, oneAPI 2025.3 + DPC++ nightly) with a Threadripper 2970WX, 128GB system running Ubuntu Server 26 LTS.

Llama-3.3-70B Q4_K_M, -sm tensor -fa 1 -ctk f16 -ctv f16:
pp512 = 377.08 t/s (vs 313.65 layer mode = +20.2%)
tg128 = 17.40 t/s (vs 9.74 layer mode = +78.6%)

Qwen3-Coder-Next-80B-A3B Q3_K_M (MoE):
pp512 = 216.56 t/s (vs 156.58 meta-backend butterfly = +38.3%)
tg128 = 17.60 t/s (vs 14.31 meta-backend butterfly = +23.0%)

Qwen3-4B Q4_K_M:
pp64 = 984.51 t/s, tg16 = 49.29 t/s

Requirements

Build/CMake: no changes. No new dependencies. ~200 lines added across ggml-sycl.h and ggml-sycl.cpp.

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: I used github copilot to help set up an automated benchmarking setup to save time. With cleanup I may try and publish the benchmarking setup dockerfile if anyone is interested

* SYCL: tensor parallelism (--split-mode tensor) for dual-GPU

Adds the comm_init/comm_free/comm_allreduce_tensor trio that the
meta-backend queries via get_proc_address to enable backend-specific
all-reduce, mirroring the pattern used by ggml-cuda.cu.

For N=2 (the common dual-GPU case) implements a degenerate ring
all-reduce with two size-branched paths:

  * Small (nelem < 32768): FP32 direct memcpy + per-device ADD kernel
    chained via depends_on(memcpy_event). 4 SYCL submissions/call.

  * Large (nelem >= 32768): BF16-compressed. Each device compresses
    FP32 -> BF16 in a local outbox, cross-device memcpys to the peer's
    inbox (HALF the PCIe bytes), then decompresses + adds into the
    local FP32 partial. 6 SYCL submissions/call but PCIe bytes halved
    -- wins for any tensor where PCIe dominates kernel time.

Threshold and BF16 path pattern mirror the CUDA NCCL allreduce.

Storage: ONE persistent uint8_t buffer per device, 4 * nelem bytes
(matches both path layouts: FP32 nelem floats; BF16 outbox+inbox =
2 * nelem uint16_t each). Single alloc+free per device keeps the
SYCL pool's strict-LIFO invariant trivial.

Initial impl handles N=2 FP32 contiguous tensors. Other cases return
false, causing the meta-backend to use its generic butterfly fallback.

Per-call sync is intentionally omitted. SYCL in-order queue semantics
ensure that the meta-backend's next compute on the same per-device
queue waits for our final ADD, and the next allreduce's first op on
the same persistent buffer waits via the same queue. Only comm_free
does an explicit final wait.

OneCCL is NOT used: OneCCL 2021.17 hardcodes single-device-per-process
in communicator_impl.hpp:47 (condition devices.size() == 1), which is
incompatible with llama.cpp's single-process multi-GPU model.

Measured on dual Intel Arc Pro B70 (NEO 26.05.x, oneAPI 2025.3 +
DPC++ nightly):

  Llama-3.3-70B Q4_K_M, -sm tensor -fa 1 -ctk f16 -ctv f16:
    pp512 = 377.08 t/s  (vs 313.65 layer mode = +20.2%)
    tg128 = 17.40 t/s   (vs   9.74 layer mode = +78.6%)

  Qwen3-Coder-Next-80B-A3B Q3_K_M (MoE):
    pp512 = 216.56 t/s  (vs 156.58 meta-backend butterfly = +38.3%)
    tg128 = 17.60 t/s   (vs  14.31 meta-backend butterfly = +23.0%)

  Qwen3-4B Q4_K_M:
    pp64  = 984.51 t/s, tg16 = 49.29 t/s

Llama-3.3-70B in SYCL TP now comfortably beats production layer mode
on both prefill and decode. Coder-Next-80B-A3B (MoE) also wins on
both — the BF16 path is what unlocks the many-medium-allreduces
prefill pattern.

Build/CMake: no changes. No new dependencies. ~210 lines added across
ggml-sycl.h and ggml-sycl.cpp.

* Fix comments
@Spruill-1 Spruill-1 requested review from a team and ggerganov as code owners June 5, 2026 00:46
@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 5, 2026
@Spruill-1 Spruill-1 changed the title Sycl Sycl --split-mode tensor Jun 5, 2026
@ggml-gh-bot

ggml-gh-bot Bot commented Jun 5, 2026

Copy link
Copy Markdown

Hi @Spruill-1, thanks for your contribution!

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

  • 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 8, 2026

Copy link
Copy Markdown
Contributor

@Spruill-1
There is no performance increasing in my test.

B580x2, Ubuntu 26.04, oneAPI 2025.3.3
I will test with more LLM.

zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -m ../models/DeepSeek-MoE-16b-Chat.Q8_0.gguf 
| model                          |       size |     params | backend    | ngl |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | --------------: | -------------------: |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 |           pp512 |        820.86 卤 7.49 |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 |           tg128 |         37.86 卤 0.01 |

zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -m ../models/DeepSeek-MoE-16b-Chat.Q8_0.gguf -sm tensor
| model                          |       size |     params | backend    | ngl |     sm |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -----: | --------------: | -------------------: |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 | tensor |           pp512 |        655.70 卤 5.28 |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 | tensor |           tg128 |         36.82 卤 0.38 |

build: 4f8f6726b (9519)


build: 4f8f6726b (9519)
zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -m ../models/DeepSeek-MoE-16b-Chat.Q8_0.gguf -fa 1 -ctk f16 -ctv f16
| model                          |       size |     params | backend    | ngl |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | --: | --------------: | -------------------: |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 |   1 |           pp512 |       823.50 卤 14.18 |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 |   1 |           tg128 |         37.90 卤 0.02 |

build: 4f8f6726b (9519)
zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -m ../models/DeepSeek-MoE-16b-Chat.Q8_0.gguf -sm tensor -fa 1 -ctk f16 -ctv f16
| model                          |       size |     params | backend    | ngl |     sm |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -----: | --: | --------------: | -------------------: |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 | tensor |   1 |           pp512 |        655.74 卤 3.83 |
| deepseek 16B Q8_0              |  16.21 GiB |    16.38 B | SYCL       |  -1 | tensor |   1 |           tg128 |         37.59 卤 0.27 |

build: 4f8f6726b (9519)

@arthw

arthw commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

@Spruill-1
I run gemma-4-26B-A4B-it-UD-Q4_K_M.gguf (16.8GB) on B580x2 (12GBx2), Host is 24GB, Ubuntu 26.04.

-sm layer (default) is successful.
-sm tensor is error: llama_bench: error: failed to create context.
Why is the error for -sm tensor?

How to avoid it for my case?


zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -fa 0,1 -m ../models/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf 
| model                          |       size |     params | backend    | ngl |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | --: | --------------: | -------------------: |
| gemma4 26B.A4B Q4_K - Medium   |  15.70 GiB |    25.23 B | SYCL       |  -1 |   0 |           pp512 |        865.38 ± 3.63 |
| gemma4 26B.A4B Q4_K - Medium   |  15.70 GiB |    25.23 B | SYCL       |  -1 |   0 |           tg128 |         57.56 ± 0.04 |
| gemma4 26B.A4B Q4_K - Medium   |  15.70 GiB |    25.23 B | SYCL       |  -1 |   1 |           pp512 |        789.92 ± 5.33 |
| gemma4 26B.A4B Q4_K - Medium   |  15.70 GiB |    25.23 B | SYCL       |  -1 |   1 |           tg128 |         57.48 ± 0.13 |

build: 4f8f6726b (9519)
zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -fa 0,1 -m ../models/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf -sm tensor
| model                          |       size |     params | backend    | ngl |     sm |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -----: | --: | --------------: | -------------------: |
llama_bench: error: failed to create context with model '../models/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf'

Thank you!

@arthw

arthw commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

For smaller LLM (5.6GB), only add -sm tensor, an error will appear.
After add -ctk f16 -ctv f16, the error disappear.

zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -fa 0,1 -m ../models/Qwen3.5-9B.Q4_K_M.gguf -sm tensor
| model                          |       size |     params | backend    | ngl |     sm |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -----: | --: | --------------: | -------------------: |
llama_bench: error: failed to create context with model '../models/Qwen3.5-9B.Q4_K_M.gguf'

zjy@svr-ai:~/ws/llama.cpp/Spruill-1_master$ ./build/bin/llama-bench -fa 1 -m ../models/Qwen3.5-9B.Q4_K_M.gguf -sm tensor -ctk f16 -ctv f16
| model                          |       size |     params | backend    | ngl |     sm |  fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -----: | --: | --------------: | -------------------: |
| qwen35 9B Q4_K - Medium        |   5.23 GiB |     8.95 B | SYCL       |  -1 | tensor |   1 |           pp512 |        581.85 ± 0.70 |
| qwen35 9B Q4_K - Medium        |   5.23 GiB |     8.95 B | SYCL       |  -1 | tensor |   1 |           tg128 |         40.75 ± 0.27 |

build: 4f8f6726b (9519)

Could you check this issue?

@arthw

arthw commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

After add -ctk f16 -ctv f16, the error of create context disappear.
But the performance of -sm tensor is -50% than -sm layer.

./build/bin/llama-bench -fa 1 -m ../models/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf -sm tensor -ctk f16 -ctv f16

-fa 1 -sm tensor -ctk f16 -ctv f16


|     sm |  fa |            test |                  t/s |
| -----: | --: | --------------: | -------------------: |
| tensor |   1 |           pp512 |        491.33 ± 6.60 |
| tensor |   1 |           tg128 |         25.97 ± 0.06 |
build: 4f8f6726b (9519)

-fa 1 -ctk f16 -ctv f16
 
|  fa |            test |                  t/s |
| --: | --------------: | -------------------: |
|   1 |           pp512 |        823.75 ± 8.41 |
|   1 |           tg128 |         57.49 ± 0.21 |

-fa 1

|  fa |            test |                  t/s |
| --: | --------------: | -------------------: |
|   1 |           pp512 |       822.71 ± 11.47 |
|   1 |           tg128 |         57.61 ± 0.11 |

@arthw

arthw commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

For bigger LLM: Qwen3.5-27B-heretic-v2-Q6_K.gguf (22GB), the performance ratio is about 1.

I think it should be more than 1 when the LLM size > 22GB.
Bigger LLM will get positive benefit.
Smaller LLM will get negative benefit, like emma-4-26B-A4B-it-UD-Q4_K_M.gguf (16.8), -50%.

But I only have B580x2 (12x2GB), so I can't test bigger LLM.
Hope others can help to verify.

The only issue is missing -ctk f16 -ctv f16 will lead to error of create context in the case -sm tensor.

./build/bin/llama-bench -fa 1 -m ../models/Qwen3.5-27B-heretic-v2-Q6_K.gguf  -sm tensor -ctk f16 -ctv f16

|     sm |  fa |            test |                  t/s |
| -----: | --: | --------------: | -------------------: |
| tensor |   1 |           pp512 |        204.51 ± 0.44 |
| tensor |   1 |           tg128 |         16.01 ± 0.14 |

build: 4f8f6726b (9519)

./build/bin/llama-bench -fa 1 -m ../models/Qwen3.5-27B-heretic-v2-Q6_K.gguf  -sm layer  -ctk f16 -ctv f16
|  fa |            test |                  t/s |
| --: | --------------: | -------------------: |
|   1 |           pp512 |        212.38 ± 1.02 |
|   1 |           tg128 |         16.33 ± 0.01 |

build: 4f8f6726b (9519)

@arthw arthw 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.

When missing -ctk f16 -ctv f16 in cmd, it will lead to error of create context in the case -sm tensor.

@sniperwhg

Copy link
Copy Markdown

As a test with heterogeneous GPU setups (1xB70, 1xB580)
Seems like there is a gain when you can run the model 1:1 split between GPUs.

For a model that will fit when split in half evenly between the two:

--bench -m /models/gemma-4-31B-it-qat-UD-Q4_K_XL.gguf -p 512,2048 -n 128,512 --split-mode tensor -ctk f16 -ctv f16

  • Memory usage allocates 8.85GB:8.75GB quantity of VRAM used between the B70 and B580
model size params backend ngl sm test t/s
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor pp512 755.44 ± 0.34
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor pp2048 616.10 ± 0.25
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor tg128 32.51 ± 0.07
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor tg512 31.50 ± 0.15

--bench -m /models/gemma-4-31B-it-qat-UD-Q4_K_XL.gguf -p 512,2048 -n 128,512 --split-mode tensor --tensor-split 3,1 -ctk f16 -ctv f16

  • Memory usage allocates 17.58GB:1.6GB quantity of VRAM used between the B70 and B580
model size params backend ngl sm ts test t/s
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor 3.00 pp512 547.67 ± 1.34
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor 3.00 pp2048 436.43 ± 0.55
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor 3.00 tg128 22.97 ± 0.02
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tensor 3.00 tg512 22.23 ± 0.04

--bench -m /models/gemma-4-31B-it-qat-UD-Q4_K_XL.gguf -p 512,2048 -n 128,512 --split-mode layer -ctk f16 -ctv f16

  • Memory usage allocates 12.5GB:5.66GB quantity of VRAM used between the B70 and B580
model size params backend ngl test t/s
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 pp512 533.35 ± 9.23
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 pp2048 544.27 ± 1.03
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tg128 23.18 ± 0.04
gemma4 31B Q4_0 16.09 GiB 30.70 B SYCL -1 tg512 22.76 ± 0.04

But what about a model that has a size greater than twice the VRAM of the smaller card?

--bench -m /models/gemma-4-31B-it-UD-Q6_K_XL.gguf -p 512,2048 -n 128,512 --split-mode tensor -ctk f16 -ctv f16
Seems to hang, doesn't finish initializing llama-bench

--bench -m /models/gemma-4-31B-it-UD-Q6_K_XL.gguf -p 512,2048 -n 128,512 --split-mode tensor --tensor-split 3,1 -ctk f16 -ctv f16

  • Memory usage allocates 28.3GB:2.3GB quantity of VRAM used between the B70 and B580
model size params backend ngl sm ts test t/s
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tensor 3.00 pp512 635.18 ± 1.05
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tensor 3.00 pp2048 490.00 ± 1.66
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tensor 3.00 tg128 15.28 ± 0.01
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tensor 3.00 tg512 15.13 ± 0.02

--bench -m /models/gemma-4-31B-it-UD-Q6_K_XL.gguf -p 512,2048 -n 128,512 --split-mode layer -ctk f16 -ctv f16

  • Memory usage allocates 19.17GB:8.71GB quantity of VRAM used between the B70 and B580
model size params backend ngl test t/s
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 pp512 627.35 ± 14.06
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 pp2048 619.17 ± 1.75
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tg128 15.16 ± 0.01
gemma4 31B Q6_K 25.62 GiB 30.70 B SYCL -1 tg512 14.96 ± 0.02

@arthw arthw 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.

@Spruill-1
This PR shows good performance increasing on multiple GPUs.

Here are the comments:

  1. Why missing the parameters -ctk f16 -ctv f16 lead to the error in create context?
  2. If the parameters -ctk f16 -ctv f16 are mandatory for this feature, please update it in SYCL.md or help in parameter -sm tensor.
  3. Please fix to avoid the error in create context when missing -ctk f16 -ctv f16. It's allowed to disable this feature in this case, but avoid the error.

Thank you!

@atsmith3

Copy link
Copy Markdown

I tested with a medium Dense (Qwen3.6-27B-UD-Q8_K_XL) and a medium MoE (Qwen3.6-35B-A3B-Q8_0) model on release b9610 as the baseline and with these PR changes applied on top of that baseline. It looks like there are gains for MoE in Prompt Processing from this change over the baseline, while token generation is approximately the same.

System Info

# HW:
Intel Core Ultra 250K Plus; 2x Arc Pro B60 GPU with PCIe Gen5 x8 to both GPUs.

# SW:
Fedora 44; Kernel 7.0.11-200.fc44.x86_64; and Intel(R) oneAPI DPC++/C++ Compiler 2026.0.0 (2026.0.0.20260331)

Dense Qwen3.6-27B-UD-Q8_K_XL

benchmark_comparison_pp512_tg128_Qwen3 6-27B-UD-Q8_K_XL
llama-batched-bench pp512 tg128 Qwen3.6-27B-UD-Q8_K_XL
| N Parallel | PP Baseline | PP PR | TGen Baseline | TGen PR |
|          1 |     164.01 |     163.04 |       9.77 |       9.76 |
|          4 |     174.50 |     173.47 |      21.32 |      21.45 |
|          8 |     187.05 |     184.06 |      36.59 |      36.17 |
|         16 |     193.75 |     194.17 |      27.69 |      27.54 |
benchmark_comparison_pp2048_tg512_Qwen3 6-27B-UD-Q8_K_XL
llama-batched-bench pp2048 tg512 Qwen3.6-27B-UD-Q8_K_XL
| N Parallel | PP Baseline | PP PR | TGen Baseline | TGen PR |
|          1 |     167.64 |     189.76 |      10.22 |      10.67 |
|          4 |     172.49 |     185.25 |      21.48 |      21.73 |
|          8 |     184.54 |     183.02 |      36.71 |      35.68 |
|         16 |     187.78 |     184.01 |      27.54 |      27.14 |

MoE Qwen3.6-35B-A3B-Q8_0

benchmark_comparison_pp512_tg128_Qwen3 6-35B-A3B-Q8_0
llama-batched-bench pp512 tg128 Qwen3.6-35B-A3B-Q8_0
| N Parallel | PP Baseline | PP PR | TGen Baseline | TGen PR |
|          1 |     235.28 |     254.19 |      17.50 |      13.72 |
|          4 |     312.07 |     334.28 |      30.24 |      28.31 |
|          8 |     367.91 |     372.97 |      45.27 |      43.57 |
|         16 |     348.05 |     384.82 |      54.67 |      53.97 |
benchmark_comparison_pp2048_tg512_Qwen3 6-35B-A3B-Q8_0
llama-batched-bench pp2048 tg512 Qwen3.6-35B-A3B-Q8_0
| N Parallel | PP Baseline | PP PR | TGen Baseline | TGen PR |
|          1 |     284.26 |     310.71 |      17.25 |      14.05 |
|          4 |     346.47 |     364.31 |      30.87 |      28.09 |
|          8 |     350.48 |     379.72 |      45.30 |      42.30 |
|         16 |     348.88 |     376.68 |      54.75 |      53.12 |

@mjsabby

mjsabby commented Jun 18, 2026

Copy link
Copy Markdown

@arthw @NeoZhangJianyu can we have Intel folks review these PRs? @ggerganov is it possible to make a label in the repo that can be used for intel b70 gpus? This way all the B70 owners can band together and test things out.

It's good for the ecosystem if Intel has a competitive software stack.

@arthw

arthw commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@mjsabby
Intel didn't support SYCL backend officially.
But we have got the support of Intel engineers: feature, bug fix, issue support and PR create/review.

For this PR, the only issue to be fixed is: missing the parameters -ctk f16 -ctv f16 lead to the error in create context.
Hope the author fix it as soon!

There is the label "SYCL" to be added to every issue and PR of SYCL backend.
It shows the issue/PR to be for Intel GPU - SYCL backend only support Intel GPU now.

It's a little complex to add the hardware/GPU mode as label to issue/PR.
There are Intel GPUs: iGPU (Arrow Lake, Lunar Lake, Panther Lake) and dGPU (A380, A770, B570, B580, B50,B60,B70) in existed issue/PR comments.
So, I think "SYCL" is enough now.

Thank you!

@mjsabby

mjsabby commented Jun 20, 2026

Copy link
Copy Markdown

@Spruill-1 the community thanks you for your contribution and would love this getting checked in. @ggerganov as well

@Spruill-1

Copy link
Copy Markdown
Contributor Author

Hey folks sorry for the delay in getting back here...

But, @arthw I think that the error is not actually '-ctk/-ctv f16', and instead is '-fa 0'. Tensor mode requires flash attention and hits this context error without.

Running the bench with -fa 0,1 will run the fa=0 case first - fail with the context error and just exit. Running here myself with '-fa 1' and without the explicit f16 runs fine, f16 is the default KV format anyway.

I'm not sure that a code change is warranted here - the guard for ensuring FA for tensor mode in production use is higher up (src/llama-context.cpp) and if my understanding of the architecture here is correct - is shared with non-SYCL backends.

I'll add a note to the sycl.md file that indicates that tensor requires flash attention.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jun 21, 2026
@Spruill-1

Copy link
Copy Markdown
Contributor Author

@arthw I pushed an additional commit to correct some multi-gpu handling with memcpy's. This had been on a separate fork on a different machine of mine and I missed it when getting this change together but was included in my original benchmarks here. (I've also done a careful walkthrough my changes to make sure I didn't miss anything else between these two systems)

A/B on dual Arc Pro B70 (-sm tensor -fa 1) (pre-warmed JIT cache):

model depth before (raw memcpy) after (dev2dev)
Qwen3.6-35B-A3B MoE 0 14.3 t/s (garbage) 15.3 t/s (coherent)
" 32k 17.5 t/s (garbage) 14.5 t/s (coherent)
Qwopus-27B dense 0 15.7 t/s (garbage) 7.4 t/s (coherent)
" 32k 17.6 t/s (garbage) 7.3 t/s (coherent)

built the PR branch as-is vs with the cross-context copy routed through dev2dev_memcpy. Note that the decrease in t/s here is largely due to my testing machine's slow device->device link bottleneck (limited to PCIe 3.0 x8 per card right now). I'd welcome benching with a newer CPU/chipset combo if anyone else has dual B70s.

@arthw

arthw commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@Spruill-1
OK, got it!
I will check the FA dependence issue on other backends for -sm tensor.
If it's common issue, we accept this limitation and it's OK to update it in SYCL.md.

I think the communication depended on the PCIE/driver and GPU hardware too.
For bigger LLM, the computing time is more than communication time, the impact of dev2dev will be smaller.

Hope more community members can help verify this PR!

Thank you!

@mjsabby

mjsabby commented Jun 22, 2026

Copy link
Copy Markdown

@Spruill-1 I'm still getting garbage after applying your change. Can you share your full command and what other modifications beyond Kernel 7.1 you have going on?

@mjsabby

mjsabby commented Jun 22, 2026

Copy link
Copy Markdown

I have a Two B70 setup on Intel host, moving to AMD host this coming weekend.

@arthw arthw 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.

It's good job!

-fa on is mandatory dependence.
When -fa off, there is crash error in CUDA backend.

-sm tensor is important feature to multiple GPUs users.
We hope it can be improved continually.

Thank you!

@arthw

arthw commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@Spruill-1
Could you handle the building error issue in CI?

Thank you!

@Spruill-1

Spruill-1 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

@arthw I'll fix the CI issue after work today - problem is my use of a 5-parameter d2d command where the upstream has moved to a 7-parameter for safety - should be an easy fix.

@mjsabby When I get the change in this evening it should resolve your problem without needing different commands - one of my earlier commands regressed it until the dev2dev memcpy fixed the regression, but that is causing this CI failure due to a silent merge conflict with upstream. Once it is in, I would be very interested in your results with dual B70s and a faster PCIe link (my old threadripper 2970wx is limiting the per-card budget to Gen 3.0 x8)

@Spruill-1

Copy link
Copy Markdown
Contributor Author

Sorry for the noise y'all - I had a spare trailing empty space on a comment line and it caused the tooling to reject it. There was also a typo to fix at the same time.

@arthw arthw added the merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. label Jun 23, 2026
Comment thread ggml/src/ggml-sycl/ggml-sycl.cpp
@mjsabby

mjsabby commented Jun 24, 2026

Copy link
Copy Markdown

Thanks @Spruill-1 works for me, thanks.

@HumerousGorgon

Copy link
Copy Markdown

For whatever reason I can't seem to build this.
By switching into the PR, it fails, complaining that there are functions that are not defined.
Am I doing something wrong?

@Spruill-1

Copy link
Copy Markdown
Contributor Author

@HumerousGorgon

For whatever reason I can't seem to build this. By switching into the PR, it fails, complaining that there are functions that are not defined. Am I doing something wrong?

How are you building? What is the command you are running and what is your repo state?

@HumerousGorgon

Copy link
Copy Markdown

@HumerousGorgon

For whatever reason I can't seem to build this. By switching into the PR, it fails, complaining that there are functions that are not defined. Am I doing something wrong?

How are you building? What is the command you are running and what is your repo state?

Fresh pull of llama.cpp, I follow SYCL build instructions, initialise environment, I try with both FP16 and FP32, build stops at the CPU section.
Latest ubuntu-server.

cmake -B build -DGGML_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DGGML_SYCL_F16=ON

cmake --build build --config Release -j -v

@Spruill-1

Spruill-1 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@HumerousGorgon If you just sync to my PR branch and try to build you'll see build issues because my branch is a bit behind the mainstream (something like ~230 commits right now). You'll need to use a merge commit of my branch played on top of main to have it fully reconciled.

@ggerganov ggerganov merged commit e9fb3b3 into ggml-org:master Jun 25, 2026
28 checks passed
papamoose pushed a commit to papamoose/llama.cpp that referenced this pull request Jun 27, 2026
* Sycl tp stage1 (#1)

* SYCL: tensor parallelism (--split-mode tensor) for dual-GPU

Adds the comm_init/comm_free/comm_allreduce_tensor trio that the
meta-backend queries via get_proc_address to enable backend-specific
all-reduce, mirroring the pattern used by ggml-cuda.cu.

For N=2 (the common dual-GPU case) implements a degenerate ring
all-reduce with two size-branched paths:

  * Small (nelem < 32768): FP32 direct memcpy + per-device ADD kernel
    chained via depends_on(memcpy_event). 4 SYCL submissions/call.

  * Large (nelem >= 32768): BF16-compressed. Each device compresses
    FP32 -> BF16 in a local outbox, cross-device memcpys to the peer's
    inbox (HALF the PCIe bytes), then decompresses + adds into the
    local FP32 partial. 6 SYCL submissions/call but PCIe bytes halved
    -- wins for any tensor where PCIe dominates kernel time.

Threshold and BF16 path pattern mirror the CUDA NCCL allreduce.

Storage: ONE persistent uint8_t buffer per device, 4 * nelem bytes
(matches both path layouts: FP32 nelem floats; BF16 outbox+inbox =
2 * nelem uint16_t each). Single alloc+free per device keeps the
SYCL pool's strict-LIFO invariant trivial.

Initial impl handles N=2 FP32 contiguous tensors. Other cases return
false, causing the meta-backend to use its generic butterfly fallback.

Per-call sync is intentionally omitted. SYCL in-order queue semantics
ensure that the meta-backend's next compute on the same per-device
queue waits for our final ADD, and the next allreduce's first op on
the same persistent buffer waits via the same queue. Only comm_free
does an explicit final wait.

OneCCL is NOT used: OneCCL 2021.17 hardcodes single-device-per-process
in communicator_impl.hpp:47 (condition devices.size() == 1), which is
incompatible with llama.cpp's single-process multi-GPU model.

Measured on dual Intel Arc Pro B70 (NEO 26.05.x, oneAPI 2025.3 +
DPC++ nightly):

  Llama-3.3-70B Q4_K_M, -sm tensor -fa 1 -ctk f16 -ctv f16:
    pp512 = 377.08 t/s  (vs 313.65 layer mode = +20.2%)
    tg128 = 17.40 t/s   (vs   9.74 layer mode = +78.6%)

  Qwen3-Coder-Next-80B-A3B Q3_K_M (MoE):
    pp512 = 216.56 t/s  (vs 156.58 meta-backend butterfly = +38.3%)
    tg128 = 17.60 t/s   (vs  14.31 meta-backend butterfly = +23.0%)

  Qwen3-4B Q4_K_M:
    pp64  = 984.51 t/s, tg16 = 49.29 t/s

Llama-3.3-70B in SYCL TP now comfortably beats production layer mode
on both prefill and decode. Coder-Next-80B-A3B (MoE) also wins on
both — the BF16 path is what unlocks the many-medium-allreduces
prefill pattern.

Build/CMake: no changes. No new dependencies. ~210 lines added across
ggml-sycl.h and ggml-sycl.cpp.

* Fix comments

* documentation update to address PR feedback

* Bring over my device-to-device memcpy chagnes

* move the dev2dev_memcpy calls to the upstream 7-parameter variety

* Fix a typo and remove a trailing whitespace
@mjsabby

mjsabby commented Jun 29, 2026

Copy link
Copy Markdown

@arthw @Spruill-1 looks like tensor mode is broken when VMM=1 for basically non trivial stuff. AI came up with a following fix, master...mjsabby:llama.cpp:sm-tensor-vmm-fix

My current workarounds are host staging or disabling VMM if I want tensor mode.

adrianhoehne pushed a commit to adrianhoehne/llama.cpp that referenced this pull request Jul 5, 2026
* Sycl tp stage1 (#1)

* SYCL: tensor parallelism (--split-mode tensor) for dual-GPU

Adds the comm_init/comm_free/comm_allreduce_tensor trio that the
meta-backend queries via get_proc_address to enable backend-specific
all-reduce, mirroring the pattern used by ggml-cuda.cu.

For N=2 (the common dual-GPU case) implements a degenerate ring
all-reduce with two size-branched paths:

  * Small (nelem < 32768): FP32 direct memcpy + per-device ADD kernel
    chained via depends_on(memcpy_event). 4 SYCL submissions/call.

  * Large (nelem >= 32768): BF16-compressed. Each device compresses
    FP32 -> BF16 in a local outbox, cross-device memcpys to the peer's
    inbox (HALF the PCIe bytes), then decompresses + adds into the
    local FP32 partial. 6 SYCL submissions/call but PCIe bytes halved
    -- wins for any tensor where PCIe dominates kernel time.

Threshold and BF16 path pattern mirror the CUDA NCCL allreduce.

Storage: ONE persistent uint8_t buffer per device, 4 * nelem bytes
(matches both path layouts: FP32 nelem floats; BF16 outbox+inbox =
2 * nelem uint16_t each). Single alloc+free per device keeps the
SYCL pool's strict-LIFO invariant trivial.

Initial impl handles N=2 FP32 contiguous tensors. Other cases return
false, causing the meta-backend to use its generic butterfly fallback.

Per-call sync is intentionally omitted. SYCL in-order queue semantics
ensure that the meta-backend's next compute on the same per-device
queue waits for our final ADD, and the next allreduce's first op on
the same persistent buffer waits via the same queue. Only comm_free
does an explicit final wait.

OneCCL is NOT used: OneCCL 2021.17 hardcodes single-device-per-process
in communicator_impl.hpp:47 (condition devices.size() == 1), which is
incompatible with llama.cpp's single-process multi-GPU model.

Measured on dual Intel Arc Pro B70 (NEO 26.05.x, oneAPI 2025.3 +
DPC++ nightly):

  Llama-3.3-70B Q4_K_M, -sm tensor -fa 1 -ctk f16 -ctv f16:
    pp512 = 377.08 t/s  (vs 313.65 layer mode = +20.2%)
    tg128 = 17.40 t/s   (vs   9.74 layer mode = +78.6%)

  Qwen3-Coder-Next-80B-A3B Q3_K_M (MoE):
    pp512 = 216.56 t/s  (vs 156.58 meta-backend butterfly = +38.3%)
    tg128 = 17.60 t/s   (vs  14.31 meta-backend butterfly = +23.0%)

  Qwen3-4B Q4_K_M:
    pp64  = 984.51 t/s, tg16 = 49.29 t/s

Llama-3.3-70B in SYCL TP now comfortably beats production layer mode
on both prefill and decode. Coder-Next-80B-A3B (MoE) also wins on
both — the BF16 path is what unlocks the many-medium-allreduces
prefill pattern.

Build/CMake: no changes. No new dependencies. ~210 lines added across
ggml-sycl.h and ggml-sycl.cpp.

* Fix comments

* documentation update to address PR feedback

* Bring over my device-to-device memcpy chagnes

* move the dev2dev_memcpy calls to the upstream 7-parameter variety

* Fix a typo and remove a trailing whitespace
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 ggml changes relating to the ggml tensor library for machine learning merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. SYCL https://en.wikipedia.org/wiki/SYCL - GPU programming language

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants