Skip to content

Thread tanh logit softcapping through FlashAttention (FA2, opt-in FA3) - #3391

Open
nvegesna-netizen wants to merge 3 commits into
NVIDIA:mainfrom
nvegesna-netizen:nvegesna/gemma2-softcap-core
Open

Thread tanh logit softcapping through FlashAttention (FA2, opt-in FA3)#3391
nvegesna-netizen wants to merge 3 commits into
NVIDIA:mainfrom
nvegesna-netizen:nvegesna/gemma2-softcap-core

Conversation

@nvegesna-netizen

Copy link
Copy Markdown
Contributor

Adds a softcap kwarg to DotProductAttention so models with attention-logit soft-capping (cap·tanh(x/cap), e.g. Gemma2) can run on TE's fused flash-attention kernels instead of falling back to an unfused/non-TE path.

Companion PRs (needed together for an end-to-end model to pick this up):

  • Megatron-LM: exposes TransformerConfig.attn_logit_softcapping and maps it to this softcap kwarg
  • Megatron-Bridge: adds an opt-in Gemma2 attention path that sets attn_logit_softcapping

What changed

  • DotProductAttention (init + forward) and AttentionParams gain a softcap: float = 0.0 kwarg. softcap=0.0 is a no-op — existing behavior is unchanged.
  • Threaded through the FA2 non-CP path and all three context-parallel autograd functions (forward + ctx-saved backward).
  • get_attention_backend: when softcap != 0, fused/unfused attention and FA3/FA4 are disqualified and selection steers to FA2 (also disqualifies FA2 builds too old to carry the softcap kernel). This is a deliberate safety net — softcap must never be silently dropped, nor hit a NotImplementedError at runtime.
  • FA3, opt-in (Hopper only): gated behind an env flag plus a build-capability probe and a head_dim <= 256 check; forward threads softcap into FA3's kwargs, backward is handled automatically by the existing Hopper autograd function. Default behavior (flag unset) is unchanged — steers to FA2.
  • Tests: forward/backward parity vs. a pure-PyTorch reference implementation.

Validation

Exercised end-to-end via the companion Megatron-LM/Megatron-Bridge changes above — multi-step training runs on both a Hopper and a Blackwell target, confirmed numerically consistent with the prior unfused path, and confirmed via kernel-level profiling that the fused flash kernels (not the fallback path) are actually selected at runtime.

Follow-up, not in this PR: FA4

FA4 softcap support is deliberately excluded here rather than included as dead scaffolding. On Blackwell (SM100), FA4's dedicated head_dim=256 forward kernel has no score_mod/softcap fusion logic in it at all — the kernel constructor asserts score_mod is None. So there's currently no FA4 kernel path capable of serving this shape; adding an opt-in flag now would just be inert code with nothing to opt into. This follows as its own PR (stacked on this branch) once — or if — an FA4 kernel with softcap fusion for head_dim=256 lands.

@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds tanh attention-logit softcapping to DotProductAttention, routes it through supported FlashAttention paths, and fails closed for unsupported backend and export combinations.

  • Adds softcap to the public attention configuration and backend-selection cache key.
  • Threads softcap through FA2 forward/backward, including context-parallel variants.
  • Adds opt-in FA3 support with capability, shape, and context-parallel guards.
  • Adds forward/backward numerical parity coverage and invokes it from L0 CI.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
transformer_engine/pytorch/attention/dot_product_attention/dot_product_attention.py Resolves and propagates softcap, includes it in backend parameters, and explicitly rejects unsupported ONNX export.
transformer_engine/pytorch/attention/dot_product_attention/utils.py Adds softcap to backend-cache inputs and filters unsupported backends, including FA3 under context parallelism.
transformer_engine/pytorch/attention/dot_product_attention/backends.py Probes FA3 softcap capability and forwards softcap through supported FA2 and opt-in FA3 execution.
transformer_engine/pytorch/attention/dot_product_attention/context_parallel.py Threads softcap through all three FA2 context-parallel forward and backward autograd paths.
tests/pytorch/attention/test_softcap.py Adds FA2 forward and gradient parity coverage across dtypes, masks, GQA, and disabled/enabled softcapping.
qa/L0_pytorch_unittest/test.sh Explicitly adds the softcap numerical test to the L0 PyTorch test job.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[DotProductAttention softcap] --> B{ONNX export?}
  B -->|Yes, nonzero softcap| C[Raise ValueError]
  B -->|No| D{Context parallel?}
  D -->|Yes| E[Select supported FA2 path]
  D -->|No| F{FA3 opt-in and capable?}
  F -->|Yes| G[FA3 forward and backward]
  F -->|No| E
Loading

Reviews (4): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile

Comment thread transformer_engine/pytorch/attention/dot_product_attention/utils.py
Comment thread tests/pytorch/attention/test_softcap.py
…in FA3)

Add a user `softcap` value (tanh logit softcapping, `softcap*tanh(x/softcap)`)
to DotProductAttention so models like Gemma2 can run on the fused flash path
instead of an unfused/FlexAttention kernel.

- Add `softcap` to DotProductAttention (init+forward) and AttentionParams;
  thread it into the FA2 non-CP kwargs and all three context-parallel autograd
  functions (forward + ctx-saved backward). softcap=0.0 reproduces prior behavior.
- get_attention_backend: when softcap != 0, disable FusedAttention/unfused and
  steer to FA2 -- disable FA3/FA4, and disable FA2 < 2.6.0 -- so the cap is never
  silently dropped (FA2 < 2.6.0) or hit at runtime as NotImplementedError (FA3/FA4).
  Also disable FA3 under context parallelism (its CP path hard-rejects nonzero
  softcap) so CP+softcap steers to FA2, which supports it, instead of crashing.
- FA3 softcap opt-in: NVTE_FA3_SOFTCAP=1, Hopper (sm90) hd<=256, non-CP only,
  gated on a fail-closed signature probe (fa3_supports_softcap). Forward threads
  softcap into fa_3_optional_forward_kwargs; the existing Hopper autograd function
  carries it into backward automatically. Default off; unchanged behavior steers
  to FA2.
- ONNX export: fail loudly (assert) rather than silently drop softcap -- export
  unconditionally force-selects UnfusedDotProductAttention, which has no softcap
  support, so this previously exported models with softcapping silently omitted.
- Tests: test_softcap.py (FA2 fwd/bwd parity vs pure-PyTorch reference), wired
  into qa/L0_pytorch_unittest/test.sh.

FA4 softcap opt-in is deliberately NOT included here -- see follow-up PR. On
Blackwell (SM100), FA4's dedicated head_dim=256 forward kernel has no score_mod
support at all (kernel constructor asserts `score_mod is None`), so there is
currently no FA4 kernel path this could opt into; adding the scaffolding now
would just be inert code with nothing to exercise.

Addresses review findings: CP+FA3 softcap selection crash, ONNX silent drop,
and the missing CI wiring for test_softcap.py.

Signed-off-by: Nitin Vegesna <nvegesna@nvidia.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nvegesna-netizen
nvegesna-netizen force-pushed the nvegesna/gemma2-softcap-core branch from a6a793b to 5917f0d Compare August 17, 2026 21:21
python -O / PYTHONOPTIMIZE strips assert statements, which would silently
reopen the ONNX export softcap-drop bug the previous commit fixed (ONNX mode
would again force-select UnfusedDotProductAttention with softcap silently
omitted, with no error). Switch to an explicit if/raise ValueError, which
survives optimized execution.

Signed-off-by: Nitin Vegesna <nvegesna@nvidia.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nvegesna-netizen
nvegesna-netizen force-pushed the nvegesna/gemma2-softcap-core branch from 19a21eb to 5ae46ce Compare August 17, 2026 21:35
for more information, see https://pre-commit.ci

(reapplied after a force-push rebase clobbered pre-commit.ci's original
19a21eb commit; same content, restored by hand)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution PRs from external contributor outside the core maintainers, representing community-driven work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant