Skip to content

vulkan: add DeepSeek-V4 hyper-connection fused ops (DSV4_HC_COMB/PRE/POST) - #26578

Open
kh0pper wants to merge 1 commit into
ggml-org:masterfrom
kh0pper:vulkan-dsv4-hc-pr
Open

vulkan: add DeepSeek-V4 hyper-connection fused ops (DSV4_HC_COMB/PRE/POST)#26578
kh0pper wants to merge 1 commit into
ggml-org:masterfrom
kh0pper:vulkan-dsv4-hc-pr

Conversation

@kh0pper

@kh0pper kh0pper commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Overview

Implements the three DeepSeek-V4 hyper-connection fused ops (DSV4_HC_COMB, DSV4_HC_PRE, DSV4_HC_POST) for the Vulkan backend. CUDA has had them since the original DeepSeek-V4 merge and Metal gained them in #26459, leaving Vulkan as the last major backend without them. On DeepSeek-V4-Flash the unfused Sinkhorn comb chain alone accounts for roughly 32% of decode op time on gfx1151 (Strix Halo), spread across about 16k dispatches per token.

Implementation

dsv4_hc_comb.comp runs the full 20-iteration Sinkhorn in registers. A token's 4x4 comb matrix occupies 16 consecutive subgroup lanes (idst in bits 0-1, isrc in bits 2-3, matching the CPU reference layout), so subgroupShuffleXor by 1|2 reduces rows and by 4|8 reduces columns. One dispatch replaces the roughly 137 strictly ordered node executions of the unfused chain per site. Shuffle masks never cross a 16-lane boundary, so a 64-wide subgroup packs 4 independent tokens.
dsv4_hc_pre.comp and dsv4_hc_post.comp handle elementwise stream collapse and fan-out, with per-token coefficients staged in shared memory.
ggml-vulkan.cpp adds the pipelines, push constants, dispatch, and supports_op entries.

Rebased onto current master as a single commit. The CONT transpose fix this PR originally carried was split out at a maintainer's request and merged as #26585, so it is now in master and both arms of the performance table below include it.

Correctness

test-backend-ops passes the full suite, including added eval cases at the production shape (n_iter=20, n_tokens 1/256/336/512/513/1024/2048).
GGML_VULKAN_CHECK_RESULTS under a real 9k-token DeepSeek-V4-Flash prompt shows 2322 comb node executions, max avg_err of 5.1e-08, zero divergent nodes.
Beyond standard checks, the ops were verified equivalent to the decomposed build_hc_sinkhorn chain, to a float64 reference, and to the official HF modeling_deepseek_v4.py formula (softmax axis, eps placements, col-first iteration order, consumer orientation), using the model's real per-layer hc_scale and hc_base weights across input magnitudes into deep softmax saturation. Max deviation between any two implementations was about 6e-7, consistent with float rounding.

Performance

gfx1151 (Strix Halo), DeepSeek-V4-Flash IQ3_XXS, 9k-token prompt, ABBA order, n=2 per arm, within-arm spread below 1%, branch rebased onto current master.

prefill t/s decode t/s
unfused 103.1 11.16
fused 115.9 16.77
ratio 1.12x 1.50x

Additional information

Greedy-decoding trajectory sensitivity. Recording this so the behavior is on record before it gets reported as a regression.

During validation, DeepSeek-V4-Flash at IQ3_XXS on one in-distribution 9k-token chat prompt produced a degenerate repetition (播客播客…) under greedy decoding on most rounding paths. The CPU backend produces it with the fused ops disabled. The previously unfused Vulkan path produced clean output on the same prompt.

No implementation is at fault. All paths agree to float epsilon, and the per-layer difference between paths grows smoothly from about 1e-9 to about 1e-3 over the 43 layers (measured with a filtered eval-callback). This is ordinary trajectory divergence of a quantized model near a degenerate attractor. Under sampled decoding (temp 0.3 and 0.7, n=8 per arm) fused and unfused outputs are indistinguishable in quality, and the worst degenerate sample came from the unfused side. DeepSeek's first-party serving endpoint produces clean greedy output on the same prompt, so the sensitivity is a property of the quantization and is absent at serving precision. CUDA and Metal users already run the fused rounding path today. Full instrumented write-up available on request.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES. AI was used to generate code with a human in the loop, to collect and reduce data from test and benchmark runs, and to organize that information into this PR description. All submitted changes were reviewed by me, and I am responsible for them.

@kh0pper
kh0pper requested review from a team and ggerganov as code owners August 4, 2026 14:01
@ggml-gh-bot

This comment was marked as resolved.

@kh0pper kh0pper changed the title Vulkan dsv4 hc pr vulkan: add DeepSeek-V4 hyper-connection fused ops (DSV4_HC_COMB/PRE/POST) Aug 4, 2026
@kh0pper
kh0pper force-pushed the vulkan-dsv4-hc-pr branch from 5f3a82a to ccbc178 Compare August 4, 2026 14:19
@github-actions github-actions Bot added testing Everything test related Vulkan Issues specific to the Vulkan backend ggml changes relating to the ggml tensor library for machine learning labels Aug 4, 2026
@jeffbolznv

Copy link
Copy Markdown
Contributor

I'd still prefer to have the transpose in a separate PR. I've looked at that part of the code and I think we could get it in pretty quickly.

@kh0pper

kh0pper commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

The transpose is now split out as #26585. I'll rebase this PR to drop that commit once it lands.

@kh0pper

kh0pper commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Closing temporarily to respect the one-open-PR limit for new contributors while #26585 (the transpose, split out at the maintainer's request) goes first. I'll reopen this after it lands and rebase to drop the shared commit.

…POST)

CUDA has these ops from the DeepSeek-V4 merge and Metal gained them in
PR 26459. Vulkan was the last major backend running the unfused primitive
chain. On DeepSeek-V4-Flash the unfused Sinkhorn comb chain alone takes
about 32% of decode op time on gfx1151 (Strix Halo), spread over roughly
16k dispatches per token.

dsv4_hc_comb runs the full 20-iteration Sinkhorn in registers. A token's
4x4 comb matrix lives in 16 consecutive subgroup lanes, with idst in bits
0-1 and isrc in bits 2-3 to match the CPU reference layout, so
subgroupShuffleXor by 1|2 reduces rows and by 4|8 reduces columns. One
dispatch replaces about 137 strictly ordered node executions per site.
The shuffle masks never cross a 16-lane boundary, so a subgroup of size
64 packs 4 independent tokens.

dsv4_hc_pre and dsv4_hc_post handle the elementwise stream collapse and
fan-out, with per-token coefficients staged in shared memory.

GGML_VK_DISABLE_DSV4_HC disables all three ops. The _COMB, _PRE and
_POST variants gate each op independently so a single kernel can be
bisected against the unfused graph.

Adds eval cases at the production n_iter=20 across batch sizes that
cross subgroup and workgroup boundaries.
@kh0pper kh0pper reopened this Aug 21, 2026
@kh0pper
kh0pper force-pushed the vulkan-dsv4-hc-pr branch from ccbc178 to 0554f85 Compare August 21, 2026 03:00
@kh0pper

kh0pper commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

@neuromaniacMD @antoinezambelli Reopened and rebased onto master as a single commit — the transpose this branch used to carry merged separately as #26585, so this PR is now just the three HC ops.

Your generation and decode numbers came from these ops, so this is the right thread for them if you're still willing to repost. The RADV gfx1100/gfx1201 offer would be welcome here too.

@antoinezambelli

Copy link
Copy Markdown

Thanks — reposting the HC-relevant results from our combined-branch test.

Tested ccbc178 across two Ryzen AI Max+ 395 / Radeon 8060S (gfx1151) systems using RADV and RPC with a 50/50 layer split. The model was DeepSeek-V4-Flash-0731 UD-Q4_K_XL at 262K context with q8 KV.

  • The focused Vulkan suite covering DSV4_HC_COMB, DSV4_HC_PRE, DSV4_HC_POST, and CONT passed 97/97 on each device.
  • Uncached generation improved from 5.55 to 12.64 tok/s: +127.8%.
  • A Forge data_gap_recovery_extended_stateful N=5 smoke retained 5/5 completion and correctness while mean wall time fell from 270.9s to 129.4s: 2.09× faster.
  • The two-node RPC path remained stable throughout.

Full hardware, driver, launch configuration, and methodology are in the original #26585 report.

@kh0pper

kh0pper commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @antoinezambelli — appreciated, especially the two-node RPC coverage.

For reviewers: ccbc178 was these three HC ops plus the #26585 transpose (in master since Aug 19). The current head 0554f85 is that same HC commit rebased onto master with comments trimmed — code unchanged — so these numbers reflect master + this PR as it stands.

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 testing Everything test related Vulkan Issues specific to the Vulkan backend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants