Skip to content

fix(cuda): saturate kernel_tanh argument (--use_fast_math tanhf overflow) - #125

Merged
dndungu merged 1 commit into
mainfrom
fix/tanh-fastmath-saturate
Jun 9, 2026
Merged

fix(cuda): saturate kernel_tanh argument (--use_fast_math tanhf overflow)#125
dndungu merged 1 commit into
mainfrom
fix/tanh-fastmath-saturate

Conversation

@dndungu

@dndungu dndungu commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Problem

internal/cuda/kernels/elementwise.cu is compiled with --use_fast_math (kernels Makefile). The fast tanhf does not saturate for large arguments -- it returns a growing value instead of ±1. This breaks the tanh-approximation GELU (0.5·x·(1+tanh(u)), u ≈ 0.0357·x³): for moderately large x the argument u reaches ~1e7, fast tanhf(u) returns a large value, GELU becomes ~quartic, and activations blow from ~1e5 to ~1e27 -> NaN in f32 (the GPU 'CrossAsset cliff'; Wolf docs/plan-gpu-f32-residual). The CPU path uses the accurate math.Tanh and is unaffected -- which masked it.

Fix

Clamp the tanhf argument to [-20, 20] in kernel_tanh and kernel_tanh_prime via a tanh_sat helper. tanh(±20) == ±1.0f exactly in float32, so this is numerically exact and keeps fast-math tanhf inside its accurate range.

Verification

Rebuilt the sm_121 libkernels.so and re-ran GB10 CrossAsset f32 training: the forward GELU over-amplification is eliminated (per-node forward scan shows zero ops exceeding 1e3, vs ~1e27 before). No Go-level unit test (GPU-kernel-only bug); belongs in the GPU parity activation suite when GPU CI is available. NOTE: production needs the kernels rebuilt/redeployed from this merge.

Status

One of two fixes for the GPU f32 cliff (the other recomputes LayerNorm stats: zerfoo#842).

…low)

elementwise.cu is compiled with --use_fast_math, whose approximate tanhf does
NOT saturate for large arguments -- it returns a growing value. This turns the
tanh-approximation GELU (0.5*x*(1+tanh(u)), u ~ 0.0357*x^3) into a quartic and
blows activations up to 1e27/NaN in f32 (GPU CrossAsset cliff; CPU's accurate
math.Tanh is unaffected). Clamp the argument to [-20,20] via tanh_sat in
kernel_tanh and kernel_tanh_prime; tanh(+/-20) == +/-1.0f is exact in float32.

Verified on GB10: rebuilt sm_121 libkernels.so eliminates the GELU forward
over-amplification (per-node forward scan: 0 ops > 1e3, was ~1e27).
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.

1 participant