Skip to content

Add: define decode DSA-CP communication and output seams - #931

Merged
zhangqi-chen merged 7 commits into
hw-native-sys:mainfrom
wangqin1723-max:feat/dsv4-flash-decode-dsa-cp-foundation
Aug 11, 2026
Merged

zhangqi-chen merged 7 commits into
hw-native-sys:mainfrom
wangqin1723-max:feat/dsv4-flash-decode-dsa-cp-foundation

Conversation

@wangqin1723-max

@wangqin1723-max wangqin1723-max commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Part of #905. This is the first replacement slice for the old CP-off attention direction in #925.

What

  • Define the TP4/SP4 decode component layout: Q-B, attention sink, and shared expert replicated; O-A, O-B, and vocabulary sharded four ways.
  • Add subgroup-local hidden-state all-gather, group-major attention-output all-to-all, and FP32 O-B reduce-scatter seams.
  • Make all three collectives capacity-static but runtime-row aware: valid rank slabs are packed at rank * local_t, and invalid tails remain untouched.
  • Add the receive-side sharded O projection: two local O-A groups, a 2048-wide O-B K shard, per-group A8 quantization, and an FP32 partial for reduce-scatter.
  • Split the SWA, HCA, and CSA decode kernels at the same group-major packed-head/task-ID boundary while preserving each legacy public wrapper and local output projection.
  • Use simulator-compatible single-buffer TPUT transfers with an 8-row communication tile.

Layout contract

Each attention core publishes [group, T_PAD, head-in-group, dim]; only the first runtime token rows in each group are valid. The all-to-all writes each source rank directly into [local_group, source_rank * local_t], producing two local O-A groups over the full TP-group token stream.

The receive-side projection consumes [LOCAL_O_GROUPS, GROUP_T_PAD, O_GROUP_IN], computes sharded O-A and O-B over only group_t = SP_SIZE * local_t, and returns a rebound [GROUP_T_PAD, hidden] FP32 partial plus its completion task ID. Reduce-scatter then sends each token owner compact local_t rows and casts only the reduced local result to BF16.

Validation\n\n- Rebased without patch changes onto main at d1cf017 (#932)\n- pre-commit run --all-files

  • Four-rank A3 simulator + exact golden for AG/A2A/RS at current S=2:
    • full capacity local_t=32
    • poisoned subcapacity local_t=31, including preserved output tails
  • Merged Add: DSpark S = 8, block-size 32 and 512-token prefill chunks #928 S=8 base: four-rank A3 simulator + exact golden at full capacity local_t=128 and dynamic subcapacity local_t=127
  • Receive-side O projection A3 simulator + golden:
  • SWA seam: A3 simulator + golden at current local T=32 and temporary S=8 local T=128
  • HCA seam: A3 simulator + golden at T=32, subcapacity T=8, and temporary S=8 T=128
  • CSA seam: T=32, subcapacity T=8, and temporary S=8 T=128 compile and complete A3 simulator runtime. The pinned local stack has a pre-existing broad CSA golden mismatch reproduced on the untouched base; after normalizing renamed symbols, all nine generated PTO kernels are byte-identical to the base.

Physical A3 CI passed the four-rank communication fixture, the strict 512/508-row receive-side O projection cases, all three staged sparse-attention programs, and the unchanged LM-head, including a fresh pass after rebasing onto d1cf017. The first A3 job had a transient unchanged LM-head S1 scheduler stall; two no-code-change A3 runs passed. Because config.py changes, simulator CI swept all 32 runnable files in the directory: both platforms passed the new communication and O-projection fixtures, then reproduced existing directory-wide mismatches (including the CSA mismatch reproduced on the untouched base with byte-identical generated kernels) and eventually stalled in unchanged lm_head.py until the 30-minute cancellation. The red simulator statuses are therefore not feature-local regressions. No physical A5 run was available. Prefill is unchanged by this PR. SWA, HCA, and CSA end-to-end output-path composition follow as decode-only slices; #913 and #923 cover the shared-expert and vocabulary boundaries.\n

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Added sequence-parallel decode communication, a receive-side grouped output projection, and staged CSA, HCA, and SWA attention paths. Existing top-level attention wrappers remain available.

Changes

DeepSeek-V4 decode pipeline

Layer / File(s) Summary
Sequence-parallel decode communication
models/deepseek_v4_flash_dspark/config.py, models/deepseek_v4_flash_dspark/decode_attention_cp.py
Added SP, updated component parallel degrees, and implemented KV all-gather, attention all-to-all, output reduce-scatter, launch wiring, fixtures, golden validation, and runtime handling.
Receive-side grouped output projection
models/deepseek_v4_flash_dspark/decode_o_projection_cp.py
Added BF16 A-projection, row-wise INT8 quantization, grouped INT8 B-projection, dequantization, accumulation, fixtures, golden validation, and test execution.
Staged sparse-attention projection
models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py, models/deepseek_v4_flash_dspark/decode_sparse_attn_hca.py, models/deepseek_v4_flash_dspark/decode_sparse_attn_swa.py
Separated head computation from local output projection. Packed head buffers and task IDs now connect both stages through top-level wrappers.

Estimated code review effort: 5 (Critical) | ~90+ minutes

Sequence Diagram(s)

sequenceDiagram
  participant Rank as SP rank
  participant Decode as decode_attention_cp
  participant Window as Distributed windows
  participant Projection as decode_o_projection_cp
  Rank->>Decode: Launch decode layout
  Decode->>Window: Gather KV tokens
  Decode->>Window: Exchange attention groups
  Window-->>Projection: Provide grouped attention rows
  Projection->>Rank: Write output partials
Loading

Possibly related PRs

Poem

A rabbit packs the heads in rows,
Then hops through gathers, waits, and flows.
INT8 scales and BF16 light,
Reduce-scatter lands outputs right.
Three staged paths now share the way—
Squeak, compile, and pass today!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the main change: adding decode DSA-CP communication and output seams.
Description check ✅ Passed The description directly explains the DSA-CP layout, communication seams, output projection, kernel splits, and validation results.

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.

@wangqin1723-max wangqin1723-max changed the title Add: define decode DSA-CP communication seams Add: define decode DSA-CP seams and SWA boundary Aug 10, 2026
@wangqin1723-max wangqin1723-max changed the title Add: define decode DSA-CP seams and SWA boundary Add: define decode DSA-CP communication and output seams Aug 10, 2026
@wangqin1723-max
wangqin1723-max marked this pull request as ready for review August 10, 2026 10:32

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
models/deepseek_v4_flash_dspark/decode_attention_cp.py (2)

276-282: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Return the poisoned tensor explicitly.

init_attention_grouped poisons grouped, then returns values. The poisoning is visible only because pl.reshape-free torch.reshape returns a view for this contiguous tensor. Any later change to the initialization chain that breaks contiguity silently removes the poisoned tail, and the fixture stops testing the capacity rows. Return the poisoned tensor in the required shape.

♻️ Proposed change
     def init_attention_grouped():
         shape = (SP_SIZE, O_GROUPS * LOCAL_T_PAD, O_GROUP_IN)
         values = torch.arange(SP_SIZE * O_GROUPS * LOCAL_T_PAD * O_GROUP_IN, dtype=torch.int32)
         values = values.remainder(127).reshape(shape).to(torch.bfloat16)
         grouped = values.reshape(SP_SIZE, O_GROUPS, LOCAL_T_PAD, O_GROUP_IN)
         grouped[:, :, local_t:] = -2000.0
-        return values
+        return grouped.reshape(shape)
🤖 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_dspark/decode_attention_cp.py` around lines 276 -
282, Update init_attention_grouped to return the poisoned grouped tensor rather
than values, preserving the shape (SP_SIZE, O_GROUPS, LOCAL_T_PAD, O_GROUP_IN)
so the local_t tail remains filled with -2000.0.

116-117: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider tiled copies instead of single-row loops.

The three seams move the window into the output one row at a time (group_out[group_row : group_row + 1, ...], the copy_row loop, and the pl.load(..., [1, D]) reduction). Each iteration is a separate GM transfer. A row-tile of COMM_ROW_TILE rows, with a clipped tail, would cut the transfer count by the tile factor. This is a fixture today, but the same seams are the template for the decode path.

Also applies to: 149-154, 183-190

🤖 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_dspark/decode_attention_cp.py` around lines 116 -
117, Replace the single-row GM copy loops in the group_out/gather_window seam,
the copy_row seam, and the pl.load reduction with COMM_ROW_TILE-row transfers,
clipping the tile size for the final partial block. Preserve the existing row
ordering, column range, and reduction behavior while reducing the number of GM
transfers.
models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py (1)

124-130: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Untyped packed-head buffers weaken the new head-to-projection seam. The split introduces o_packed_heads as a bare pl.Tensor in all three head stages and in the matching local projection stages. The layout is fixed by compile-time constants at every call site, but the missing annotation removes the shape and dtype check exactly where the two new stages meet. The SWA stage uses a head-major layout while CSA and HCA use a group-major layout, so a swapped buffer would compile.

  • models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py#L124-L130: annotate o_packed_heads as pl.Tensor[[O_GROUPS * T_PAD, O_GROUP_IN], pl.BF16], and apply the same annotation to o_packed in sparse_attn_csa_local_o_proj at Line 427.
  • models/deepseek_v4_flash_dspark/decode_sparse_attn_hca.py#L132-L138: annotate o_packed_heads as pl.Tensor[[O_GROUPS * T_PAD, O_GROUP_IN], pl.BF16] here and at Line 392.
  • models/deepseek_v4_flash_dspark/decode_sparse_attn_swa.py#L103-L109: annotate o_packed_heads as pl.Tensor[[O_GROUPS * T_PAD * HEADS_PER_GROUP, HEAD_DIM], pl.BF16] here and at Line 294, which keeps the head-major layout explicit at the boundary and documents why Line 322 reshapes.
🤖 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_dspark/decode_sparse_attn_csa.py` around lines 124 -
130, Annotate the packed-head parameters with their fixed layout and BF16 dtype:
in models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py lines 124-130 and
sparse_attn_csa_local_o_proj at line 427, use the group-major shape; in
models/deepseek_v4_flash_dspark/decode_sparse_attn_hca.py lines 132-138 and line
392, use the same group-major shape; and in
models/deepseek_v4_flash_dspark/decode_sparse_attn_swa.py lines 103-109 and line
294, use the head-major shape. Preserve these annotations at each
head-to-projection boundary.
🤖 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.

Inline comments:
In `@models/deepseek_v4_flash_dspark/decode_o_projection_cp.py`:
- Around line 180-186: Update build_tensor_specs to validate local_t before
calculating group_t, rejecting non-positive values such as the subcapacity case
when local_t is zero. Match the range-validation behavior used by
decode_attention_cp.build_tensor_specs, while preserving valid capacity
handling.

---

Nitpick comments:
In `@models/deepseek_v4_flash_dspark/decode_attention_cp.py`:
- Around line 276-282: Update init_attention_grouped to return the poisoned
grouped tensor rather than values, preserving the shape (SP_SIZE, O_GROUPS,
LOCAL_T_PAD, O_GROUP_IN) so the local_t tail remains filled with -2000.0.
- Around line 116-117: Replace the single-row GM copy loops in the
group_out/gather_window seam, the copy_row seam, and the pl.load reduction with
COMM_ROW_TILE-row transfers, clipping the tile size for the final partial block.
Preserve the existing row ordering, column range, and reduction behavior while
reducing the number of GM transfers.

In `@models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py`:
- Around line 124-130: Annotate the packed-head parameters with their fixed
layout and BF16 dtype: in
models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py lines 124-130 and
sparse_attn_csa_local_o_proj at line 427, use the group-major shape; in
models/deepseek_v4_flash_dspark/decode_sparse_attn_hca.py lines 132-138 and line
392, use the same group-major shape; and in
models/deepseek_v4_flash_dspark/decode_sparse_attn_swa.py lines 103-109 and line
294, use the head-major shape. Preserve these annotations at each
head-to-projection boundary.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c55a8142-ebac-4d2e-b1c3-f32304debf5f

📥 Commits

Reviewing files that changed from the base of the PR and between b97d959 and 0976ae2.

📒 Files selected for processing (6)
  • models/deepseek_v4_flash_dspark/config.py
  • models/deepseek_v4_flash_dspark/decode_attention_cp.py
  • models/deepseek_v4_flash_dspark/decode_o_projection_cp.py
  • models/deepseek_v4_flash_dspark/decode_sparse_attn_csa.py
  • models/deepseek_v4_flash_dspark/decode_sparse_attn_hca.py
  • models/deepseek_v4_flash_dspark/decode_sparse_attn_swa.py

Comment thread models/deepseek_v4_flash_dspark/decode_o_projection_cp.py
@wangqin1723-max
wangqin1723-max force-pushed the feat/dsv4-flash-decode-dsa-cp-foundation branch 2 times, most recently from db957d2 to d5f894d Compare August 10, 2026 12:01
- Set the TP4/SP4 component layout for replicated Q-B, attention
  sinks, and shared experts plus sharded output and vocab projections
- Add group-local KV gather, grouped attention all-to-all, and O-B
  reduce-scatter seams with a four-rank golden fixture
Split the legacy local output projection from the SWA head computation so decode DSA-CP can insert its group-major all-to-all at the exact tensor and task dependency boundary. Keep the public wrapper and numerical behavior unchanged.
- Thread the runtime local token count through AG, A2A, and RS.
- Pack valid rank rows compactly inside static-capacity windows.
- Cover sub-capacity rows with poisoned inputs and preserved output tails.
- Use simulator-compatible one-buffer TPUT transfers with 8-row tiles.
- Project compact runtime token prefixes through sharded O-A and O-B
- Keep O-B matmuls in 128-row slabs and expose FP32 completion
- Cover max-capacity and poisoned-tail receive layouts in the golden fixture
Split the local output projection from HCA head computation so decode DSA-CP can insert its group-major all-to-all at the tensor and task dependency boundary. Keep the public wrapper and numerical behavior unchanged.
@wangqin1723-max

Copy link
Copy Markdown
Collaborator Author

Latest-main CI disposition for head d5f894d on main@d1cf017:

  • Pre-commit, unit tests, build, and physical A3 all pass.
  • The A3 job passed the new four-rank communication fixture, strict 512/508-row O projection, and all CSA/HCA/SWA staged programs.
  • Updating config.py makes simulator CI sweep all 32 runnable dspark files. Both simulators passed decode_attention_cp.py and decode_o_projection_cp.py, then reproduced existing directory-wide mismatches. The changed CSA wrapper has the same broad mismatch reproduced on untouched main, with all nine generated PTO kernels byte-identical after symbol normalization.
  • Both simulator jobs eventually stalled in unchanged lm_head.py and were canceled at the 30-minute workflow limit.

I am treating the simulator statuses as baseline/runtime debt, not changing DSA-CP kernels or tolerances to mask them.

@zhangqi-chen
zhangqi-chen merged commit a92a983 into hw-native-sys:main Aug 11, 2026
9 of 11 checks passed

# Parallelism constants
TP = 4 # tensor-parallel ranks per DP group
SP = TP # sequence-parallel token owners in the TP group

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

delete sp

@@ -0,0 +1,287 @@
# Copyright (c) PyPTO Contributors.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

in next pr, rename this to decode_o_proj.py,put all o proj related functions within it, including communication, tp=1 functions.

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.

2 participants