Repository navigation
Conversation
…op-k for Hopper Triton drop-in for prime-rl's dsv41_index_topk (same signature, same picks up to ties) that never materializes the (queries, entries) fp32 score matrix: - a dense FP8 GEMM (per-token UE8M0 quantization, as prime-rl) keeps only the max of every doc-local group of entries and of every 4 groups; - a persistent per-query kernel selects the best groups by their max (the top topk_blocks pinned candidate blocks on candidate source layers); - a persistent per-query kernel rescores only the entries of the top topk groups and radix-selects; candidate consumer layers score only their candidate entries. The top-k groups by max provably contain the top-k entries, so this is exact. Forward only (the indexer is frozen). Tests vs an fp64 reference of the FP8 math, plus a benchmark against prime-rl's op at V4.1 Flash shapes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The expert MLP of a rank's local experts for training on SM90: tokens already grouped by expert, DeepSeek-V4's clamped SwiGLU (gate clamped to max=l, up to [-l, l]), bf16, forward and backward. It is the Hopper-feasible core of cuDNN's MegaMoE expert compute; dispatch and the routing scores stay with the caller. The token-major grouped GEMMs are persistent, warp-specialized Gluon kernels: two consumer warpgroups run the wgmma K loop of a 128x256 tile (issuing TMA loads STAGES-1 steps ahead, across tiles) and park the bf16 tile in shared memory, and an epilogue warpgroup finishes it while the next tile's K loop runs: - fc1: gate and up of the same columns in one 256-wide MMA, SwiGLU in the epilogue, - down, - dh: the SwiGLU backward in the epilogue (dgate, dup) plus the recomputed h, - dx: dgate @ gate_proj + dup @ up_proj in one K loop. Only x, gate and up are saved for backward. Weight gradients use torch._grouped_mm, which beat a Gluon version. Exposed as a torch.library custom op with fake and autograd registrations; separate or packed gate/up weights. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # README.md # prime_kernels/kernels.toml
Triton forward and backward for the V4.1 manifold-constrained hyper-connection projection on SM90: - forward: one pass over the (tokens, hc, d) streams computes the per-token RMS statistic, the bf16 x bf16 -> fp32 projection to the (2 + hc) * hc gate logits, and the collapse of the streams by the previous sublayer's pre gate - backward: TMA-fed kernel writing dx (projection, RMS and collapse terms), deterministic split-token dW partials, and d(pre_mix) as the diagonal of a tensor-core grad_collapsed @ x.T - gates: sigmoid pre/post and Sinkhorn comb, forward and backward, in one kernel each Exposed as torch.library custom ops with fake impls; hyper_connection chains them. Tests compare against fp64/fp32 torch references; the benchmark compares against prime-rl's DeepseekV41HyperConnection + collapse_streams. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # README.md # prime_kernels/kernels.toml
…ation) moe_experts(..., fp8=True) runs the expert MLP in DeepSeek-V3 blockwise FP8 for the forward, the data gradients and the weight gradients: e4m3, fp32 scales, 1x128 groups along K for activations/gradients (per 128 tokens of each channel for the weight-gradient operands), 128x128 blocks for weights, fp32 accumulation; SwiGLU math in fp32 as in bf16. The GEMMs are DeepGEMM's m-grouped (1d2d) and k-grouped (1d1d) FP8 GEMMs. Around them: - one Gluon/TMA pass over x (and dout) writes both the per-row FP8 copy in a 128-row padded layout and the per-column, transposed copy the k-grouped weight-gradient GEMM reads, - the SwiGLU forward pass writes FP8 h; the SwiGLU backward pass writes FP8 dgate|dup per row and per column and FP8 h per column, - the down and dx GEMMs write out/dx in place at the tokens' rows; the up-to-127 head rows per expert that land in a block starting in the previous expert are recomputed by a small head GEMM and scattered (no unpad pass), - weights are quantized once per call with their transposed copies in the same pass, - no host synchronization. Tests compare against an fp32 reference and an exact torch emulation of the FP8 recipe; the benchmark adds the FP8 variants, prime-rl's DeepGEMM path, a per-kernel breakdown and an accuracy report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rnels" This reverts commit 4d4c00b.
…ttention Drop-in for prime-rl's dsv41_sparse_attn_backward (FlashMLA forward + cuDNN SM90 DSA backward today): shared K = V latent buffer, per-query slot lists with -1 empty slots, per-head attention sink, 64 heads x 512. - Triton preprocess: delta = rowsum(dO * O), sink-aware LSE, dsinks, and compaction of each query's non-empty slots to the front. - CuTe DSL main kernel (SM90, wgmma): persistent, one query per iteration, two warpgroups. WG0: S / dP / softmax / dQ[:, :256] with dS from registers; WG1: dQ[:, 256:] and dKV in 64-column chunks scattered with fp32 v4 atomics (4 rows x 128 B per instruction after a quad swap). The single-buffered KV tile is refilled half by half as soon as each half's last reader is done; the next query's Q / dO halves are TMA-loaded while the current query's last dKV chunks still run. - Triton postprocess: undo the atomics' column permutation, cast to bf16. - torch.library op prime_kernels::dsa_sparse_attn_bwd with a fake impl. At V4.1 shapes (16k queries, 640 slots, 16k + 8k kv rows) on H200: 8.71 ms vs cuDNN 10.42 ms (1 doc, 1.20x) and 8.26 vs 10.15 ms (4 packed docs, 1.23x); results within 1e-4 / 3e-4 / 3e-6 (dq / dkv / dsinks, rel L2) of cuDNN and at cuDNN's error vs an fp32 reference. The dKV atomics (~21 GB per call) bound the kernel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fused stream-gradient sum moe_experts (FP8, Hopper): - `moe_experts_fp8_quantize_weights` / `moe_experts_fp8_forward_quantized`: quantize expert weights once per optimizer step and reuse them across micro-batches. - `moe_experts_fp8_backward_accumulate`: accumulate weight gradients straight into a caller's fp32 buffer (FSDP's), skipping a separate add. - Split backward ops (data gradient first, weight gradients after) so a caller can send the data gradient before the weight-gradient GEMMs run. mhc_projection: - `mhc_projection_streams` / `hyper_connection_streams`: return the streams as a view so the post-update's gradient is added inside the projection backward (`grad_x_addend`), bit for bit the sum autograd would compute, instead of a separate full-size add. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hannels were rewritten in place The forward's caller applies the inverse RoPE in place to each head's last channels; out_tail carries the original channels so the backward's delta = rowsum(dO * O) stays exact. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WG1 loads P^T and dS^T once per tile with ldmatrix.trans and runs its six dKV chunks as RS wgmmas, instead of re-reading both from shared memory for every chunk (-96 KB of shared memory traffic per tile), and hands P / dS back to WG0 right after dQ_hi. Two rotating dKV accumulators instead of three make room for the fragments. Bitwise identical per contribution (checked with unique kv rows, where the atomics are deterministic); KERNEL_OPTS rs=0 restores the old path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… one pass, optional inverse RoPE One CTA per [128 tokens x 128 channels] tile reads the bf16 matrix once and writes both of prime-rl's casts (per_token_cast_to_fp8_triton and per_token_cast_to_fp8_tp_triton) bit for bit, optionally of dsv4_rope(x, inverse=True) (the DeepSeek-V4.1 query gradient). 8192 x 32768: 383 us vs 509 us for the three Triton passes (no RoPE: 319 vs 463). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hopper (SM90) training kernels for DeepSeek-V4.1 Flash. They port what cuDNN frontend 1.30 ships for the DeepSeek-V4 family on Blackwell only. All three are Python-only (Triton / Gluon),
arch = ["9.0"].dsa_indexer_topk: Lightning Indexer forward fused with top-k and the two-level candidate-block filter. It is a drop-in for prime-rl'sdsv41_index_topk: same arguments, same picks up to ties. It never builds the(queries, entries)score matrix. A dense FP8 pass keeps per-group maxima, the best groups are rescored, and candidate consumer layers score only their candidates. Forward only, because the indexer is frozen.moe_experts: expert MLP of a rank's local experts: grouped GEMMs with the clamped SwiGLU fused into a warp-specialized epilogue, forward and backward. Onlyx,gateandupare saved. Weight gradients usetorch._grouped_mm.moe_experts(..., fp8=True): DeepSeek-V3 blockwise FP8 (1x128 activation/gradient scales, 128x128 weight blocks, FP8 forward, dgrad and wgrad). It runs DeepGEMM's grouped FP8 GEMMs with the quantization fused into the surrounding passes:x(anddout) writes the row-quantized copy and the transposed column-quantized copy that wgrad reads;h, and the SwiGLU backward writes FP8dgate|dup;dsa_sparse_attn_bwd: SM90 backward for V4.1's sparse attention (64 heads × 512, shared latent K = V, attention sink), a drop-in for cuDNN's DSA backward.mhc_projection: mHC projection (RMS + gate logits + collapse of the streams by the previous sublayer'spre) in one read of the streams per direction, plus fused gate activations (sigmoid, Sinkhorn). dW is deterministic.Each has a
torch.librarycustom-op surface with fake impls and works undertorch.compile(fullgraph=True). prime-rl picks each kernel up behindprime_kernels.is_availableand keeps its own path otherwise.Results (H200)
FP8 weight cache, split backward, fused mHC stream gradient
moe_experts_fp8_quantize_weights/moe_experts_fp8_forward_quantized: quantize expert weights once per optimizer step and reuse them across micro-batches (+8.7% on a PP2×4 V4.1 proxy, less memory).moe_experts_fp8_backward_accumulate: accumulate FP8 weight gradients straight into a caller's fp32 buffer such as FSDP's (+9.1% on the same proxy).mhc_projection_streams/hyper_connection_streams: return the streams as a view so the post-update's gradient is added inside the projection backward (grad_x_addend), bit for bit the sum autograd computes, instead of a separate full-size add (−0.47 ms per V4.1 layer).tests/mhc_projectiongains one test; the module's 16 tests pass.Sparse-attention backward and FP8 dual cast (DeepSeek-V4.1 pipeline stage)
dsa_sparse_attn_backward(..., out_tail=): for a forward output whose per-head last channels the caller rewrote in place (prime-rl's in-place RoPE on the attention output),out_tailholds the original channels sodelta = rowsum(dO * O)stays exact.tests/dsa_sparse_attn_bwdgains one test.KERNEL_OPTS["rs"] = 0restores the old path.fp8_dual_cast(CuTe): per-token and transposed per-token e4m3 casts in one pass, with an optional inverse RoPE. prime-rl uses it for the query-gradient path and everyFloat8BlockwiseLineargrad_output: cast kernels per V4.1 layer 0.93 → 0.77 ms. FP8 bytes and scales are bitwise-identical to the separate casts.These three were validated on H200 inside prime-rl's stage bench (bitwise checks as above). The module tests were not rerun after rebasing them onto this branch.
Testing
tests/{dsa_indexer_topk,moe_experts,mhc_projection}: forward and backward against fp32/fp64 torch references on small odd shapes and V4.1 shapes, plus meta/compile checks. 52 passed on H200 (FP8 outputs and grads also checked against an exact torch emulation of the recipe and against prime-rl's DeepGEMM path). Eachtests/<name>/bench_<name>.pyreproduces its numbers.Known gaps
moe_expertsuses Gluon, which is experimental in Triton 3.7.mhc_projectionautotunes on first use per shape.🤖 Generated with Claude Code