Skip to content

Perf: fan out DeepSeek V4-flash hc_head over idle cores - #822

Merged
zhangqi-chen merged 1 commit into
hw-native-sys:mainfrom
zhangqi-chen:perf/dsv4-flash-hc-head-decode-fanout
Jul 23, 2026
Merged

Perf: fan out DeepSeek V4-flash hc_head over idle cores#822
zhangqi-chen merged 1 commit into
hw-native-sys:mainfrom
zhangqi-chen:perf/dsv4-flash-hc-head-decode-fanout

Conversation

@zhangqi-chen

Copy link
Copy Markdown
Collaborator

Summary

  • Fan hc_head_reduce over (token-tile x D-slice) and fold the rsqrt/sigmoid gate into it, deleting the hc_head_pre_fused scope and the transposed pre_t GM buffer. At decode (T=8, one token-tile) the reduce previously ran as a single task, so one core streamed all 512KB of x_flat while the other 23 idled.
  • Split the rms sum-of-squares over RMS_OK K-slices, each writing its own sq_part row; the consumer sums the rows and applies rsqrt inline, so the inv_rms buffer is gone as well.
  • Raise LINEAR_OK 8 -> 16 to fill the idle cubes.
  • Zero mixes_raw via pl.create_tensor(init_value=0) on the AICPU instead of a hc_head_seed kernel, which cost ~5us of wall on the cube's critical path to zero 1KB.
  • Size sq_part / mixes_raw from the dynamic t_dim / t_linear instead of a static T_MAX, so decode (8 rows) and prefill (128 rows) each allocate what they use.
  • Rename RMS_K_CHUNK / LINEAR_K_CHUNK / D_CHUNK to *_K_TILE / D_TILE; prefill_mtp.py's aliased imports follow.

Five scopes drop to three. Isolated hc_head span 58.8 -> 42.6 us (median of 5, decode T=8, a2a3 single card), with run-to-run spread narrowing from 45-65 us to 39-43 us.

At decode (T=8, one token-tile) both the rms and the reduce scopes ran
as a single task, so one core streamed all 512KB of x_flat while the
other 23 idled.

- Fan the reduce over (token-tile x D-slice) and fold the rsqrt/sigmoid
  gate into it, deleting the hc_head_pre_fused scope and the transposed
  pre_t GM buffer
- Split the rms sum-of-squares over RMS_OK K-slices into per-slice
  sq_part rows; the consumer sums them and applies rsqrt inline, so the
  inv_rms buffer is gone too
- Raise LINEAR_OK 8 -> 16 to fill the idle cubes
- Zero mixes_raw with create_tensor(init_value=0) on the AICPU instead
  of a hc_head_seed kernel, which cost ~5us of wall on the cube's
  critical path to zero 1KB
- Size sq_part / mixes_raw from the dynamic t_dim rather than a static
  T_MAX, so decode (8) and prefill (128) each allocate what they use

Five scopes drop to three. Isolated hc_head span 58.8 -> 42.6 us
(median of 5, decode T=8, a2a3 single card), and run-to-run spread
narrows from 45-65 us to 39-43 us.

Constants renamed *_K_CHUNK -> *_K_TILE; prefill_mtp's aliased imports
follow.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The DeepSeek-V4 HC-head implementation now uses tile-based RMS and linear split-K computation, intermediate accumulation buffers, and direct final reduction. Golden HC-head and packed-prefill reference paths use the updated tile constants.

Changes

HC-head tiled compute rewrite

Layer / File(s) Summary
HC-head tiling and compute pipeline
models/deepseek/v4-flash/hc_head.py
Tiling constants and split factors are replaced, while hc_head computes sq_part and mixes_raw through partitioned accumulation before producing gated BF16 output. The golden reference loops use the renamed tile constants.
Prefill reference integration
models/deepseek/v4-flash/prefill_mtp.py
Packed-prefill imports and golden accumulation loops use RMS_K_TILE and LINEAR_K_TILE sizing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant hc_head
  participant RMS_partitions
  participant LINEAR_partitions
  participant final_reduce
  hc_head->>RMS_partitions: Partition sum-of-squares into sq_part
  hc_head->>LINEAR_partitions: Accumulate projection blocks into mixes_raw
  RMS_partitions->>final_reduce: Supply sq_part
  LINEAR_partitions->>final_reduce: Supply mixes_raw
  final_reduce->>hc_head: Write BF16 y_flat
Loading

Possibly related PRs

Poem

A rabbit hopped through tiles of light,
Split-K paths ran swift and bright.
RMS sums joined the final flow,
Raw mixes bloomed in atomic glow.
BF16 carrots filled the tray—
HC-head bounds a better way!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main performance change to hc_head and is concise and specific.
Description check ✅ Passed The description is directly aligned with the code changes and accurately summarizes the optimization work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
models/deepseek/v4-flash/hc_head.py (1)

17-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reinstate divisibility assertions for tile constants.

The prior T_MAX/assertions that validated tiling constants against HC_DIM/D are removed here. Without them, a future change to hc_mult/hidden_size (which drive HC_DIM/D) could silently violate HC_DIM % (RMS_OK * RMS_K_TILE) == 0, HC_DIM % (LINEAR_OK * LINEAR_K_TILE) == 0, or D % D_SPMD == 0 / D_SPMD % D_TILE == 0, causing the reduction loops to skip trailing K/D ranges with no error surfaced.

🛡️ Suggested guard
 LINEAR_OK = 16
 RMS_OK = 16
+
+assert HC_DIM % (RMS_OK * RMS_K_TILE) == 0
+assert HC_DIM % (LINEAR_OK * LINEAR_K_TILE) == 0
+assert D % D_SPMD == 0 and D_SPMD % D_TILE == 0

Based on the provided line-range change details noting "the earlier derived T_MAX and several transpose/chunk-derived constants and assertions are no longer part of this configuration section."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@models/deepseek/v4-flash/hc_head.py` around lines 17 - 42, Reinstate
validation near the tiling constants in the model configuration: assert that
HC_DIM is divisible by RMS_OK * RMS_K_TILE and LINEAR_OK * LINEAR_K_TILE, and
that D is divisible by D_SPMD and D_SPMD is divisible by D_TILE. Restore any
required derived T_MAX or related tiling guards used by these checks, without
changing the existing tile values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@models/deepseek/v4-flash/hc_head.py`:
- Around line 17-42: Reinstate validation near the tiling constants in the model
configuration: assert that HC_DIM is divisible by RMS_OK * RMS_K_TILE and
LINEAR_OK * LINEAR_K_TILE, and that D is divisible by D_SPMD and D_SPMD is
divisible by D_TILE. Restore any required derived T_MAX or related tiling guards
used by these checks, without changing the existing tile values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a7733cfa-c26f-4c61-afa6-b91c550faa46

📥 Commits

Reviewing files that changed from the base of the PR and between 7a63278 and 35378bc.

📒 Files selected for processing (2)
  • models/deepseek/v4-flash/hc_head.py
  • models/deepseek/v4-flash/prefill_mtp.py

@zhangqi-chen
zhangqi-chen merged commit 3f67f0d into hw-native-sys:main Jul 23, 2026
12 of 17 checks passed
@zhangqi-chen
zhangqi-chen deleted the perf/dsv4-flash-hc-head-decode-fanout branch July 24, 2026 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant