Gpu numerical safety
Skill ytfh44/gpu-optimize-skills/skills/gpu-numerical-safety
An evidence-driven Agent Skills suite for GPGPU performance engineering, from kernels and compilers to memory, resource, and runtime-state management.
npx -y skills add ytfh44/gpu-optimize-skills --skill gpu-numerical-safetyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 22 days oldThe repository was created 22 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Load this skill and follow it when optimizing GPU code that may change floating-point evaluation order, precision, boundary behavior, NaN or Inf propagation, determinism, or other program semantics.
SKILL.md
13.1 KB, as published. Nobody here has run it
GPU Numerical Safety
Skill navigation
- Parent/orchestrator: gpu-code-optimizer
- gpu-performance-evidence — load to measure the performance benefit independently of correctness
- gpu-reductions-scans — load for reduction trees, scans, prefix operations, and recurrence boundaries
- gpu-training-autodiff — load when gradients, saved tensors, or mixed precision are involved
- gpu-optimization-validation — load for acceptance gates and failure-case reporting
Load linked skills only when their trigger applies. Do not duplicate their full workflow here.
Core rule
An optimization is not safe because the algebra is equivalent over real numbers. GPU optimizations frequently change evaluation order, contraction, precision, masking order, synchronization, aliasing, and boundary behavior. Classify the semantic risk before promoting a fast path.
Optimization classification
Every optimization must be labeled with exactly one risk class. This prevents treating "algebraically equivalent" rewrites as "bitwise identical" rewrites.
| Class | Name | Description |
|---|---|---|
| C1 | Strict semantic equivalent | Program semantics are unchanged and output is expected to be bitwise-identical against the reference. If compiler lowering, fusion, contraction, or instruction selection changes floating-point evaluation order, classify the change as C2 instead. |
| C2 | Floating-order changed | Mathematically equivalent but floating-point accumulation order differs. May produce small numerical differences whose magnitude depends on dtype, reduction length, input scale, and conditioning. |
| C3 | Approximate with tolerance | Introduces an explicit approximation (clipping, truncation, fast math, reduced precision). Must document the error bound and the value range where it holds. |
| C4 | Semantics changed | Behavior differs from the reference path in ways that go beyond floating-point reordering. Requires explicit user approval. Never the default path. |
Rules:
- C3 and C4 optimizations must be opt-in fast paths, not silent replacements of the original code. The original correct path must remain available as a fallback.
- C2 optimizations may become the default only when their error stays within the existing accepted tolerance, does not require relaxing tests, and shows no systematic drift or boundary-case regression. If a C2 change requires tolerance relaxation, it must be gated like a fast path and paired with the reference fallback.
- Any C2 or higher optimization must document the numerical difference explicitly: max abs error, max relative error, and which inputs produce the worst case.
- Do not label a change C1 just because the math works out on paper. Floating-point arithmetic is not real arithmetic. Reduction trees, scan ordering, product chains, mask-before vs mask-after, and accumulate-then-broadcast vs broadcast-then-accumulate all change floating-point semantics.
Scope of the C1–C4 labels
The C1–C4 labels are a conversational shorthand for this skill suite. They may be spoken to the user or to a parent agent when reporting the risk class of a change.
The C1–C4 labels must not be written into the codebase. Do not put C1/C2/C3/C4 into source comments, docstrings, identifiers, variable names, enum values, configuration keys, commit messages, branch names, tags, file names, or generated code. When the codebase itself must record the risk class, use a descriptive name (for example, floating_point_reorder, approximate_with_tolerance, semantics_changed) and keep the C1–C4 mapping in the surrounding conversation, pull request, or decision record instead.
Default-safe-path rule
Any optimization that changes floating-point stability, accumulation order, truncation behavior, mask semantics, boundary handling, NaN/Inf propagation, denormal treatment, determinism, or synchronization semantics must not unconditionally replace the original path.
Such optimizations must be:
- Gated behind a parameter, compile-time flag, runtime check, or configuration switch.
- Paired with a documented fallback to the original correct implementation.
- Accompanied by guard conditions (see the guard-condition template below).
The default code path must remain safe and correct. Fast paths are opt-in.
Guard-condition template
Every fast path must declare its guard conditions explicitly. Use this template:
Fast path is enabled only when:
- dtype is ...
- shape satisfies ...
- rank is ...
- layout / stride pattern is ...
- alignment is ...
- value range is ...
- precision mode is ...
- deterministic mode is ...
- training / inference mode is ...
- gradient required / no-gradient is ...
- device capability / architecture is ...
- chunk / block / tile size is ...
Otherwise use fallback path: <name or description>.
Common guard categories:
- Type guards: dtype, precision mode, mixed-precision configuration.
- Shape guards: minimum/maximum dimensions, divisibility, rank.
- Layout guards: contiguous, channel-last, channel-first, striding, alignment.
- Value guards: range (non-negative, normalized, bounded), presence of NaN/Inf/denormal.
- Hardware guards: device capability, architecture generation, driver version.
- Mode guards: training vs inference, gradient required, deterministic mode, debug mode.
- Aliasing guards: input/output overlap, in-place update safety.
Guard design rules
A guard must be checkable and tied to the actual precondition. Avoid vague statements such as “for normal inputs” or “for supported shapes.” Express the condition in terms of dtype, dimensions, strides, alignment, architecture, value range, determinism mode, gradient requirements, aliasing, or other observable properties.
Do not use a guard to hide an uncharacterized correctness defect. If a fast path is wrong for inputs inside its declared domain, shrink or remove the domain until the implementation is correct.
When the runtime cost of a value-domain check would erase the speedup, use one of these patterns:
- enforce the contract at an API boundary and document it;
- assert in debug/test builds and trust a stronger upstream invariant in production;
- compute a cheap conservative predicate;
- keep the reference path as the default and make the optimization explicit opt-in.
Numerical discipline
Error reporting (mandatory for C2+)
For any optimization that changes numerics, report all of the following:
| Metric | Required |
|---|---|
| Max absolute error | ✓ |
| Mean absolute error | ✓ |
| P95 / P99 absolute error | ✓ |
| Max relative error | ✓ |
| Mean relative error | ✓ |
| P95 / P99 relative error | ✓ |
Normalised error (‖new − ref‖ / ‖ref‖) | ✓ |
| ULP error (if bit-level precision matters) | optional |
| NaN count in output | ✓ |
| Inf count in output | ✓ |
| Signed-zero differences | optional |
| Worst-case input shape | ✓ |
| Worst-case random seed | ✓ |
| Error vs sequence length / batch size trend | ✓ |
| Systematic bias direction (new > ref or new < ref) | ✓ |
Do not report only max abs diff. Small denominators inflate relative error; large outputs hide absolute error. Report both.
Tolerance rule
Relaxing a correctness tolerance is a semantic decision, not a debugging shortcut. Before relaxing any tolerance, answer:
- Is the error from floating-point accumulation reordering (C2) or from an explicit approximation (C3)?
- Is there truncation, clipping, or saturation?
- Does error grow with sequence length, batch size, or input magnitude?
- Does error concentrate on extreme inputs or distribute uniformly?
- Is a more numerically stable formulation available?
- Should the fast path be opt-in rather than default?
Tolerance values are contracts. Do not raise them without explaining the root cause.
Numerical pathology checklist
When an optimization introduces division, cumprod, exp, log, reciprocal, rsqrt, subtraction of nearly-equal values, prefix-product, normalisation, softmax, or log-sum-exp, perform a dedicated numerical stability analysis:
- Can the operation produce NaN?
- Can the operation produce ±Inf?
- Can intermediate values underflow to zero (especially cumprod chains)?
- Can intermediate values overflow (especially division by subnormals)?
- Does the optimization change how subnormals are handled (flush-to-zero vs gradual underflow)?
- Does the optimization change signed-zero behavior?
- Does the optimization change the rounding path?
- Does the optimization change how extreme inputs propagate?
- Does the optimization change mask-before vs mask-after ordering (∞·0 = NaN risk)?
- Does the optimization push a scale factor into or out of a reduction?
Math equivalence does not guarantee floating-point safety. Every division, cumprod, and exp chain needs explicit guardrails.
Value-range and distribution contract
Many fast paths make implicit assumptions about input values. Document them:
- Are inputs expected to be non-negative? Normalised?
- Is there an expected bound on scale, gate values, probabilities, or weights?
- Can extreme values, NaN, or Inf appear in valid inputs?
- Can subnormals appear? Does the fast path handle them or flush them?
- Does the fast path depend on a specific random distribution?
- Does it depend on early-training vs late-training statistics?
- Does it depend on parameter initialization range?
- Does it depend on quantization scale range?
If a fast path depends on a value-range assumption, it needs a runtime assert, debug assert, documentation, or fallback.
Boundary semantics
Boundary rules are part of semantics. Explicitly test inclusive/exclusive conventions, masks, padding, tails, chunk boundaries, empty inputs, singleton dimensions, and non-divisible sizes.
For operations with masks or infinities, order matters. Examples:
- masking before versus after exponentiation;
- multiplying a masked value by zero when the unmasked value may be Inf;
- subtracting maxima before exponentiation;
- accumulating a scale inside versus outside a reduction;
- applying clipping before versus after normalization;
- changing an exclusive scan to inclusive plus shift.
These changes may alter NaN propagation, signed zero, underflow, overflow, and rounding even when the intended mathematical result appears equivalent.
Mixed precision and fast math
Treat reduced precision, tensor-float modes, approximate transcendentals, flush-to-zero behavior, and contraction/FMA changes as explicit numerical choices.
Before enabling a lower-precision path, record:
- storage dtype and compute/accumulation dtype;
- cast points and rounding modes where relevant;
- scale/normalization strategy;
- saturation or clipping behavior;
- range of intermediate values;
- whether the reference uses a higher-precision accumulator;
- expected error growth with reduction length or depth.
Do not classify a precision change as C1. It is usually C2 or C3 depending on whether the mathematical operation remains exact but the evaluation order/precision changes, or whether an explicit approximation is introduced.
Determinism, atomics, and parallel reductions
A faster reduction or atomic scheme can change result order across runs. Distinguish:
- deterministic algorithm with different but stable order;
- nondeterministic scheduling that changes accumulation order run to run;
- semantically different conflict resolution;
- implementation-defined behavior that the reference never guaranteed.
If deterministic mode is a supported user contract, a nondeterministic fast path requires an explicit guard and fallback. Performance comparisons must report whether deterministic mode is enabled on both paths.
Test corpus
For C2+ changes, test more than random normal data. Include:
- zeros, signed zeros, all-equal values;
- tiny/subnormal-scale values where supported;
- very large finite values near overflow thresholds;
- NaN and ±Inf where valid inputs may contain them;
- cancellation-heavy patterns;
- monotone increasing/decreasing sequences;
- sparse and highly skewed values;
- lengths around block/chunk boundaries;
- multiple seeds and representative real inputs.
Sweep dimensions that control error growth: reduction length, sequence length, number of recurrent steps, batch size, and scale magnitude.
Acceptance rule
C1 requires semantic equivalence and expected bitwise identity under the same execution semantics. C2 requires existing accepted tolerance without silently relaxing tests. C3 requires an explicit approximation contract and opt-in or otherwise clearly approved behavior. C4 requires explicit user approval.
A speedup that only passes after unexplained tolerance relaxation is not accepted. Route the result to gpu-optimization-validation with the full error report and failure cases.