@@ -44,20 +44,35 @@ def scaled_masked_softmax_forward_torch(
4444 mask : torch .Tensor ,
4545 scale : float ,
4646) -> torch .Tensor :
47- # Handle uint8 mask (CUDA format: 1=masked, 0=unmasked)
48- # Convert to additive mask (-10000 for masked positions, 0 for unmasked)
49- if mask .dtype == torch .uint8 :
50- additive_mask = torch .zeros_like (input , dtype = input .dtype )
51- # Expand mask if needed (mask shape: batch, 1, seq_q, seq_k)
52- if mask .dim () == 4 and mask .size (1 ) == 1 and input .dim () == 4 :
53- mask = mask .expand_as (input )
54- additive_mask = additive_mask .masked_fill (mask .bool (), - 10000.0 )
55- else :
56- additive_mask = mask
57-
58- scaled_input = input * scale + additive_mask
59-
60- return F .softmax (scaled_input , dim = - 1 )
47+ """Reference forward matching TE CUDA `scaled_masked_softmax_warp_forward`.
48+
49+ Integer/bool mask (same as uint8 kernel contract):
50+ - **Exactly** ``mask == 1`` means **masked** (logit set to ``-10000``, not ``input*scale`` offset).
51+ - Any other value (typically 0) means **unmasked** (logit is ``input * scale``).
52+
53+ Floating mask: treated as **additive** bias in logit space (already scaled), added after
54+ ``input * scale``.
55+
56+ Common pitfalls this avoids vs the old implementation:
57+ 1) ``input * scale + (-10000)`` on masked positions ≠ CUDA's plain ``-10000``.
58+ 2) Non-uint8 masks (bool, int) were used as direct addends → wrong (0/1 added to logits).
59+ 3) ``mask.bool()`` masks any nonzero byte; CUDA only masks when ``mask == 1``.
60+ """
61+ if mask .dim () == 4 and mask .size (1 ) == 1 and input .dim () == 4 :
62+ mask = mask .expand_as (input )
63+
64+ scaled = input * scale
65+
66+ if mask .is_floating_point ():
67+ scaled = scaled + mask .to (dtype = scaled .dtype )
68+ return F .softmax (scaled , dim = - 1 )
69+
70+ # Integer / bool: align with CUDA (masked iff value == 1)
71+ scaled = scaled .masked_fill (mask == 1 , - 10000.0 )
72+ # CUDA zeros output row when every position in the softmax dim is masked (max == -10000)
73+ all_masked = (mask == 1 ).all (dim = - 1 , keepdim = True )
74+ out = F .softmax (scaled , dim = - 1 )
75+ return out .masked_fill (all_masked , 0.0 )
6176
6277
6378def scaled_masked_softmax_backward_torch (
0 commit comments