You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Every TP weight shard is replicated across CP ranks, so its local weight-gradient contributions require CP SUM during backward.
The implementation is built on the fixed-order det_gemm_fwd, det_gemm_da, and det_gemm_db arithmetic introduced by #180. This issue remains GEMM-only: it covers rank-local GEMM arithmetic, fixed tensor ownership, explicit TP/CP reduction operators, and operator-level numerical validation.
The forward track is shared by rollout and training forward. The backward track is training-only and must not be inferred from the forward communication path.
Target Configuration
Model: Qwen3-8B dense transformer layer
Architecture: NVIDIA SM90
Input/output and activation-gradient dtype: BF16
Local GEMM accumulation dtype: FP32
Tensor parallelism: TP=2
Context parallelism: CP=2
Data parallelism: DP=1
Physical topology: 2 nodes x 2 GPUs per node, 4 ranks total
Sharding: even TP and CP shards only
Execution scope: standalone operator-level forward and backward
Integration scope: standalone RL-Kernel operators and tests only
Version 1 freezes BF16 local partial outputs and synchronous in-place BF16 reductions. FP32 communication partials and FP32 gradient buffers are separate TODO items.
gate = GEMM(x, W_gate)
up = GEMM(x, W_up)
hidden = activation(gate) * up
output = GEMM(hidden, W_down)
There are three logical GEMM calls:
Gate projection.
Up projection.
Down projection.
This issue does not pack Gate and Up into one projection. Gate and Up call det_gemm independently. The missing activation/multiply forward and backward boundaries are listed in TODO. Backward tests therefore use independent deterministic dGate, dUp, and dOutput fixtures; this issue does not claim a complete Qwen3 MLP forward or backward result.
This formula assumes DP=1, an even sequence shard, and a dense/padded layout. TP does not split M_local.
Ranks on different nodes process different sequence shards. For the same TP lane, the GEMM weight shard is replicated across CP:
rank0 and rank2 own the TP0 weight shard
rank1 and rank3 own the TP1 weight shard
Ranks on the same node process the same sequence shard and differ because of TP:
Gate/Up: the GEMM input rows are identical inside a TP group; the weight/output-column shards differ.
Down: both the hidden-feature shard and the matching weight K-shard differ; the two local outputs are partial sums.
CP does not require activation AllGather inside these GEMM operators. Forward CP AllGather may be used only by the test harness to reconstruct the global sequence.
During backward, the CP group has a different role: it sums local dW contributions for the same replicated TP weight shard. The operator accepts an explicit gradient group; version 1 requires that group to equal the fixed two-rank CP group. It does not infer or create DP/CP groups.
Why Gate/Up Are ColumnParallel and Down Is RowParallel
Use the mathematical Linear layout:
Y[M,N] = X[M,K] @ W[K,N]
ColumnParallel: split W along N/output features
RowParallel: split W along K/input-reduction features
The selected layout is not the only mathematically possible layout. It is the only layout under the fixed version-1 ownership contract that preserves the TP shard through the nonlinear boundary, returns to the replicated residual stream, and does not add an avoidable TP gather or reduction.
Gate and Up must use the same global intermediate-feature offsets. Then every rank can complete the nonlinear boundary locally:
hidden_i = SiLU(gate_i) * up_i
No TP AllReduce or AllGather is required between Gate/Up and Down because SiLU and multiplication are elementwise and do not mix different intermediate-feature coordinates.
The nonlinear boundary is the reason RowParallel Gate/Up is a poor layout. If Gate/Up split the input/reduction dimension, each rank would produce same-coordinate partials:
gate = gate_partial_0 + gate_partial_1
up = up_partial_0 + up_partial_1
The partials cannot pass through SiLU independently because, in general:
SiLU(a + b) != SiLU(a) + SiLU(b)
Nor can the multiply be distributed over independently incomplete Gate and Up values. Both complete Gate and complete Up must therefore be TP-reduced before activation. That adds two logical reductions over [M_local,12288] tensors, or the same bytes as one packed [M_local,24576] reduction, before Down starts.
ColumnParallel Gate/Up removes those reductions entirely and keeps only [M_local,6144] local shards.
Down must consume the intermediate with RowParallel
After the local nonlinear boundary, each rank owns:
hidden_i: [M_local,6144]
This is already a shard of Down's input/reduction dimension. RowParallel aligns the matching weight shard:
The reduction produces the complete [M_local,4096] residual-stream tensor on both TP ranks. It requires exactly one logical MLP-forward TP reduction.
ColumnParallel Down would require every TP rank to receive the complete [M_local,12288] intermediate before GEMM, so it first needs a TP AllGather. It would then produce an output-hidden shard [M_local,2048], while the fixed residual stream is TP-replicated [M_local,4096]; residual add would require another ownership conversion or a different sequence-parallel contract.
Therefore the fixed forward communication comparison is:
selected layout:
Gate/Up Column -> local SiLU/multiply -> Down Row
communication: one TP reduction of [M_local,4096]
RowParallel Gate/Up alternative:
communication before nonlinearity:
Gate reduction [M_local,12288]
Up reduction [M_local,12288]
plus a later ownership conversion/Down reduction
ColumnParallel Down alternative:
gather full intermediate [M_local,12288]
plus convert output ownership before replicated residual
This issue freezes the selected layout. TP sequence parallel may define a different residual ownership and use AllGather/ReduceScatter, but that is a different operator contract and remains out of scope.
Training TP/CP Communication Guide
The MLP training path must be read in reverse during backward. CP continues to shard token rows; TP continues to shard feature/weight dimensions.
Forward
X_cp: CP-local token rows, TP-replicated hidden [M_local,4096]
Gate/Up ColumnParallel:
local GEMMs
no TP collective
no CP collective
SiLU + multiply:
local TP feature shards
no TP collective
no CP collective
Down RowParallel:
local output partial
TP AllReduce over [M_local,4096]
no CP collective
CP activation AllGather is not part of any MLP GEMM forward. Attention has a separate CP KV exchange, but Attention is outside this issue.
Backward activation gradients
Backward starts with dOutput:[M_local,4096], which is CP-sharded by token and replicated inside the TP group.
Down RowParallel backward:
dHidden_i = dOutput @ W_down_i^T # [M_local,6144]
Each rank owns a different intermediate-feature shard, so dHidden_i remains local and does not use TP AllReduce.
After the elementwise activation/multiply backward, each rank has aligned dGate_i and dUp_i. Gate/Up ColumnParallel backward produces same-coordinate input-gradient contributions:
That is one logical TP reduction over [M_local,4096]. Version 1 of this issue lacks the activation/multiply backward, so PR6 validates the generic ColumnParallel dX communication operator on Gate and Up independently. Combining both local contributions before one TP reduction remains an explicit TODO and must not be claimed by PR6.
CP does not AllGather dX; different CP ranks continue to own gradients for different token rows.
Backward weight gradients
Each CP rank computes weight-gradient contributions from its local token rows:
These are CP weight-gradient reductions, not CP activation AllGathers and not TP reductions. Under the fixed topology they cross nodes. With DP>1, the same mathematical contributions must be reduced once over the correct combined DP x CP replica group; generic group construction is outside version 1.
Gate, Up, and Down are three logical parameter gradients. PR7 validates them independently. A training framework may pack them into gradient buckets and use fewer physical collective calls, but bucket count is not part of this standalone operator contract.
For the complete non-sequence-parallel MLP, the communication-minimal mathematical target is:
forward:
one TP reduction at Down
backward activation:
one TP reduction after locally combining Gate and Up dX contributions
backward weights:
one CP/DP replica reduction per logical weight gradient
physical calls may be bucketed
Version 1 intentionally tests Gate/Up dX and the three dW tensors independently so every failure has one arithmetic and one process-group explanation. Later fusion/bucketing may reduce call count only after this reference contract passes.
Fixed Forward GEMM Shapes and Communication
det_gemm uses A[M,K] @ B[K,N] -> C[M,N].
GEMM
TP sharding
Global B[K,N]
TP=2 local input
TP=2 local B
Local output
Forward collective
Gate
Column / N
[4096,12288]
[M_local,4096]
[4096,6144]
[M_local,6144]
None
Up
Column / N
[4096,12288]
[M_local,4096]
[4096,6144]
[M_local,6144]
None
Down
Row / K
[12288,4096]
[M_local,6144]
[6144,4096]
[M_local,4096] partial
TP AllReduce SUM
Gate and Up produce different output-column shards and do not sum across TP ranks.
The TP reduction is required because different output-feature shards contribute to the same dX coordinates. The CP reduction is required because CP ranks process different tokens while owning replicas of the same TP weight shard.
Gate and Up are independent in version 1. Combining their rank-local dX contributions before one TP reduction requires the missing activation/multiply backward and is a TODO.
RowParallel backward does not TP-reduce dHidden_i: each rank owns a different intermediate-feature shard. Its replicated weight shard still requires CP gradient reduction.
Qwen3 MLP projections have no bias in this scope, so bias-gradient reduction is not included.
Forward and Backward Communication Matrix
Path
Gate/Up ColumnParallel
Down RowParallel
Forward activation
local GEMM; no TP collective
local partial GEMM + TP AllReduce
Backward activation
local dX partial GEMM + TP AllReduce
local TP-sharded dHidden; no TP collective
Backward weight
local dW + CP AllReduce over same TP lane
local dW + CP AllReduce over same TP lane
This matrix is the reason forward and backward must be separate PR tracks. A forward communication wrapper cannot be reused as the backward wrapper by changing tensor names.
Numerical and Topology Boundary
Every communication GEMM must expose or test both sides of its reduction:
Because local partials are rounded before communication, TP=2/CP=2 output is not required to be bitwise equal to a TP=1/CP=1 GEMM that performs one uninterrupted global reduction. It must match the fixed distributed reference and satisfy the shared #108 tolerance against the global FP32 oracle.
Test reports must state:
COVERED:
2 nodes x 2 GPUs per node
TP=2, CP=2, DP=1, even shards
two IntraNode TP AllReduce groups
two InterNode CP weight-gradient AllReduce groups
NOT COVERED:
TP groups crossing nodes
TP=4, CP=4, or larger world sizes
DP>1 or a combined DP x CP gradient group
uneven K/N or sequence shards
bitwise equality across different NCCL algorithms, protocols, or rank mappings
WS2 Qwen3-8B Deterministic GEMM Forward/Backward + TP/CP Reductions
Status: Draft
Related work:
Background
Roadmap #83 places distributed and parallelism invariance under WS2. This issue validates Qwen3-8B GEMM behavior under a fixed TP=2, CP=2 deployment.
Forward and backward are separate communication contracts:
The implementation is built on the fixed-order
det_gemm_fwd,det_gemm_da, anddet_gemm_dbarithmetic introduced by #180. This issue remains GEMM-only: it covers rank-local GEMM arithmetic, fixed tensor ownership, explicit TP/CP reduction operators, and operator-level numerical validation.The forward track is shared by rollout and training forward. The backward track is training-only and must not be inferred from the forward communication path.
Target Configuration
Version 1 freezes BF16 local partial outputs and synchronous in-place BF16 reductions. FP32 communication partials and FP32 gradient buffers are separate TODO items.
Qwen3 MLP GEMM Flow
The relevant Transformers implementation is
Qwen3MLP.forward:Expanded into observable GEMM boundaries:
There are three logical GEMM calls:
This issue does not pack Gate and Up into one projection. Gate and Up call
det_gemmindependently. The missing activation/multiply forward and backward boundaries are listed in TODO. Backward tests therefore use independent deterministicdGate,dUp, anddOutputfixtures; this issue does not claim a complete Qwen3 MLP forward or backward result.Fixed TP/CP Rank Layout
Process groups:
CP splits the sequence dimension:
This formula assumes DP=1, an even sequence shard, and a dense/padded layout. TP does not split
M_local.Ranks on different nodes process different sequence shards. For the same TP lane, the GEMM weight shard is replicated across CP:
Ranks on the same node process the same sequence shard and differ because of TP:
CP does not require activation AllGather inside these GEMM operators. Forward CP AllGather may be used only by the test harness to reconstruct the global sequence.
During backward, the CP group has a different role: it sums local
dWcontributions for the same replicated TP weight shard. The operator accepts an explicit gradient group; version 1 requires that group to equal the fixed two-rank CP group. It does not infer or create DP/CP groups.Why Gate/Up Are ColumnParallel and Down Is RowParallel
Use the mathematical Linear layout:
The selected layout is not the only mathematically possible layout. It is the only layout under the fixed version-1 ownership contract that preserves the TP shard through the nonlinear boundary, returns to the replicated residual stream, and does not add an avoidable TP gather or reduction.
Gate/Up must use aligned ColumnParallel shards
For Qwen3-8B:
ColumnParallel splits the intermediate/output dimension:
Gate and Up must use the same global intermediate-feature offsets. Then every rank can complete the nonlinear boundary locally:
No TP AllReduce or AllGather is required between Gate/Up and Down because SiLU and multiplication are elementwise and do not mix different intermediate-feature coordinates.
The nonlinear boundary is the reason RowParallel Gate/Up is a poor layout. If Gate/Up split the input/reduction dimension, each rank would produce same-coordinate partials:
The partials cannot pass through SiLU independently because, in general:
Nor can the multiply be distributed over independently incomplete Gate and Up values. Both complete Gate and complete Up must therefore be TP-reduced before activation. That adds two logical reductions over
[M_local,12288]tensors, or the same bytes as one packed[M_local,24576]reduction, before Down starts.ColumnParallel Gate/Up removes those reductions entirely and keeps only
[M_local,6144]local shards.Down must consume the intermediate with RowParallel
After the local nonlinear boundary, each rank owns:
This is already a shard of Down's input/reduction dimension. RowParallel aligns the matching weight shard:
The reduction produces the complete
[M_local,4096]residual-stream tensor on both TP ranks. It requires exactly one logical MLP-forward TP reduction.ColumnParallel Down would require every TP rank to receive the complete
[M_local,12288]intermediate before GEMM, so it first needs a TP AllGather. It would then produce an output-hidden shard[M_local,2048], while the fixed residual stream is TP-replicated[M_local,4096]; residual add would require another ownership conversion or a different sequence-parallel contract.Therefore the fixed forward communication comparison is:
This issue freezes the selected layout. TP sequence parallel may define a different residual ownership and use AllGather/ReduceScatter, but that is a different operator contract and remains out of scope.
Training TP/CP Communication Guide
The MLP training path must be read in reverse during backward. CP continues to shard token rows; TP continues to shard feature/weight dimensions.
Forward
CP activation AllGather is not part of any MLP GEMM forward. Attention has a separate CP KV exchange, but Attention is outside this issue.
Backward activation gradients
Backward starts with
dOutput:[M_local,4096], which is CP-sharded by token and replicated inside the TP group.Down RowParallel backward:
Each rank owns a different intermediate-feature shard, so
dHidden_iremains local and does not use TP AllReduce.After the elementwise activation/multiply backward, each rank has aligned
dGate_ianddUp_i. Gate/Up ColumnParallel backward produces same-coordinate input-gradient contributions:The communication-minimal complete MLP backward would do:
That is one logical TP reduction over
[M_local,4096]. Version 1 of this issue lacks the activation/multiply backward, so PR6 validates the generic ColumnParalleldXcommunication operator on Gate and Up independently. Combining both local contributions before one TP reduction remains an explicit TODO and must not be claimed by PR6.CP does not AllGather
dX; different CP ranks continue to own gradients for different token rows.Backward weight gradients
Each CP rank computes weight-gradient contributions from its local token rows:
Weights are TP-sharded but replicated across CP. Only ranks with the same TP coordinate own the same weight coordinates, so reductions are:
These are CP weight-gradient reductions, not CP activation AllGathers and not TP reductions. Under the fixed topology they cross nodes. With DP>1, the same mathematical contributions must be reduced once over the correct combined DP x CP replica group; generic group construction is outside version 1.
Gate, Up, and Down are three logical parameter gradients. PR7 validates them independently. A training framework may pack them into gradient buckets and use fewer physical collective calls, but bucket count is not part of this standalone operator contract.
Training communication summary and PR ownership
dHiddendXdWFor the complete non-sequence-parallel MLP, the communication-minimal mathematical target is:
Version 1 intentionally tests Gate/Up
dXand the threedWtensors independently so every failure has one arithmetic and one process-group explanation. Later fusion/bucketing may reduce call count only after this reference contract passes.Fixed Forward GEMM Shapes and Communication
det_gemmusesA[M,K] @ B[K,N] -> C[M,N].B[K,N]BN[4096,12288][M_local,4096][4096,6144][M_local,6144]N[4096,12288][M_local,4096][4096,6144][M_local,6144]K[12288,4096][M_local,6144][6144,4096][M_local,4096]partialGate and Up produce different output-column shards and do not sum across TP ranks.
Down computes:
The forward communication operator accepts an explicit
tp_group. It does not initialize process groups, infer global rank mappings, or use a CP group.Fixed Backward GEMM Shapes and Communication
Gate/Up ColumnParallel backward
For each Gate or Up projection on TP lane
i:The TP reduction is required because different output-feature shards contribute to the same
dXcoordinates. The CP reduction is required because CP ranks process different tokens while owning replicas of the same TP weight shard.Gate and Up are independent in version 1. Combining their rank-local
dXcontributions before one TP reduction requires the missing activation/multiply backward and is a TODO.Down RowParallel backward
For TP lane
i:RowParallel backward does not TP-reduce
dHidden_i: each rank owns a different intermediate-feature shard. Its replicated weight shard still requires CP gradient reduction.Qwen3 MLP projections have no bias in this scope, so bias-gradient reduction is not included.
Forward and Backward Communication Matrix
dXpartial GEMM + TP AllReducedHidden; no TP collectivedW+ CP AllReduce over same TP lanedW+ CP AllReduce over same TP laneThis matrix is the reason forward and backward must be separate PR tracks. A forward communication wrapper cannot be reused as the backward wrapper by changing tensor names.
Numerical and Topology Boundary
Every communication GEMM must expose or test both sides of its reduction:
This separates local
det_gemmdrift from collective dtype, group, stream, and summation-order drift.In the fixed rank layout:
dXcover IntraNode TP AllReduce.dWcovers InterNode CP AllReduce.Version 1 defines the distributed BF16 oracle explicitly:
Because local partials are rounded before communication, TP=2/CP=2 output is not required to be bitwise equal to a TP=1/CP=1 GEMM that performs one uninterrupted global reduction. It must match the fixed distributed reference and satisfy the shared #108 tolerance against the global FP32 oracle.
Test reports must state:
Goals
det_gemm_fwd,det_gemm_da, anddet_gemm_dbimplementation from [WS1][kernels] Batch-invariant deterministic GEMM (fwd + bwd) #180; do not create another GEMM arithmetic core.det_gemm_fwdfollowed by BF16 TP AllReduce SUM.dXas localdet_gemm_dafollowed by BF16 TP AllReduce SUM.dHiddenremains TP feature-sharded and requires no TP collective.dWas localdet_gemm_dbfollowed by BF16 CP AllReduce SUM over the explicit same-TP-lane group.Non-Goals
Planned PRs
Forward and backward are separate tracks. Each PR adds one new arithmetic or communication boundary and has an independent oracle.
Dependency / #180: stabilize local det_gemm forward and backward primitives
det_gemm_fwd,det_gemm_da, anddet_gemm_db.cuda_sm90backend and fail closed when it is unavailable.(K,N)=(4096,6144)and(6144,4096)plus the matching localdAanddBshapes.dB=A^T@dCas a reduction over localM; do not claim bitwise invariance across different CP partitions or early-rounding boundaries.Forward track
PR2: fixed TP=2, CP=2 forward shard references
PR3: fixed TP=2 Down forward communication GEMM
hidden_local,weight_local, and an explicittp_group.det_gemm_fwd.PR4: 2-node x 2-GPU forward validation
[0,1],[2,3]and CP groups[0,2],[1,3]in the test launcher.det_gemm_fwdindependently on both CP shards.NOT COVERED.Backward track
PR5: fixed TP=2, CP=2 backward shard references
dGate,dUp, anddOutputfixtures.dX_partial, DowndHidden_i, and Gate/Up/DowndW_local_ishapes and values without NCCL.dXand CP sums for everydWshard.dHidden_iremains TP feature-sharded and must not be TP-reduced.PR6: fixed TP=2 ColumnParallel backward dX communication GEMM
dOutput_local,weight_local, and an explicittp_group.dX_partialwithdet_gemm_da.PR7: fixed CP=2 replicated-weight dW communication GEMM
input_local,dOutput_local, and an explicitgrad_group.dW_localwithdet_gemm_db.dWshapes independently.local_dw_pre_cp_reduceanddw_post_cp_reducewith PR5.PR8: 2-node x 2-GPU backward validation and reproducibility report
[0,1]and[2,3].[0,2]and[1,3].dHiddenremains local while Gate/UpdXis TP-reduced.NOT COVERED.TODO
dXcontribution before one TP reduction.