Dense linear algebra operations represent the core computational bottleneck across numerical physics workloads, including explicit linear solves, Gaussian Process (GP) regression, reduced-order modeling, and Partial Differential Equation (PDE) Green’s function evaluations. On consumer NVIDIA Ampere GPUs (such as the RTX 3080), these dense matrix multiplications default to half-rate execution on Tensor CoresDedicated matrix-multiply units on NVIDIA GPUs that multiply small fp16 tiles and add up the products, far faster than the general-purpose CUDA cores for dense matmul. when configured with FP32 accumulators.
By enabling FP16 accumulator execution via PyTorch’s allow_fp16_accumulation flag, matrix multiplication throughput increases by 1.91× for matrix inverse applications and 1.84× for PDE Green’s function solves, while maintaining relative errors near against double-precision (FP64) reference baselines.
Mathematical Equivalence Across Dense Physical Systems
Despite structural differences in underlying physics equations, four distinct scientific computing tasks reduce to identical linear algebra operations:
- Dense Linear Solves: Operator factorization is performed once, followed by multiple triangular solves across right-hand side (RHS) vector blocks.
- Gaussian Process / Kernel Ridge Regression: Dense covariance matrices are inverted once, followed by matrix-vector evaluations over evaluation queries.
- Reduced-Order Models: Physical systems are projected onto reduced basis subspaces, followed by repeated matrix-vector applications across parameter sweeps.
- PDE Green’s Functions: Discrete differential operators are inverted once to construct Green’s function representations, which are subsequently applied across spatial source distributions.
In each workload, operator construction occurs once, while operator application (a dense GEMMGeneral matrix-matrix multiply, the dense C = A·B kernel that sits at the center of all four workloads.) repeats across time steps, parameter samples, or batch inputs.
Mathematical reduction of physics solvers to GEMM operators
Each workload decomposes into a two-phase execution lifecycle:
- Phase 1: Operator Formation (Amortized): Construct operator matrix or its inverse .
- Phase 2: Operator Application (Hot Loop): Compute , where contains right-hand side columns.
Because Phase 2 executes for every batch or ensemble evaluation, optimizing the underlying matrix-matrix product directly reduces total execution time.
Computational Amortization: Formation vs. Application
Profiling an matrix inversion demonstrates the performance disparity between operator formation and operator application:
- Operator Formation (
torch.linalg.inv): 202.0 ms (executed once in FP32). - Operator Application ( for ): 4.46 ms in FP32-accumulator mode vs. 2.34 ms in FP16-accumulator mode.
Because operator formation occurs once at initialization, optimizing application latency dominates total wall-clock time as the number of RHS evaluations grows.
When applications are performed per formation step, execution time becomes entirely application-dominated, and the speedup ratio approaches .
Amortization economics in ensemble simulations
In uncertainty quantification (UQ) and Monte Carlo sampling, an operator is initialized once and applied to thousands of RHS vectors. Under these conditions, setup overhead () becomes negligible compared to cumulative application time ( per 1,000 passes).
NVIDIA Ampere Tensor Core Accumulator Architecture
NVIDIA Tensor Cores process matrix multiply-accumulate (MMAMatrix multiply-accumulate: the tensor-core primitive that multiplies two input tiles and adds the product into a running accumulator. A GEMM is built from many of these.) primitives by multiplying FP16 input tiles and accumulating products into a running sum:
On consumer NVIDIA Ampere hardware (microarchitecture sm_86, e.g., RTX 3080), Tensor Cores support two accumulation modes:
- FP32 Accumulation (fp32-accumulateSumming the running dot product in single precision. Numerically safe on any input, but on sm_86 GeForce it issues at half the rate of fp16 accumulation.): Accumulates intermediate products in FP32 precision. On consumer Ampere, this instruction path executes at half hardware throughput.
- FP16 Accumulation (fp16-accumulateSumming the running dot product in half precision. Same fp16 inputs, same cores, but on sm_86 it issues at the full MMA rate.): Accumulates intermediate products in FP16 precision, issuing at full hardware clock rates.
By default, cuBLASNVIDIA's dense linear-algebra library, the GEMM backend PyTorch calls. It defaults to fp32 accumulation because that is correct on any input. selects FP32 accumulation to prevent potential numerical overflow across arbitrary workloads.
Hardware issue rates on consumer vs. datacenter silicon
On consumer Ampere (sm_86), hardware design choices enforce a 1:2 issue rate penalty for FP32 accumulation relative to FP16 accumulation. On datacenter Ampere (sm_80, A100) and Hopper (sm_90, H100), FP32 and FP16 accumulation execute at identical issue rates. Consequently, FP16 accumulator speedups apply specifically to consumer-grade GPU hardware.
Evaluating Arithmetic Intensity for dense operator application
For an matrix product (), total arithmetic work is . Total memory traffic for FP16 inputs and outputs is .
This yields an arithmetic intensityFloating-point operations performed per byte of memory traffic. High intensity means a kernel is limited by compute, not by memory bandwidth. of , placing execution deep within the compute-boundLimited by how fast the arithmetic units retire operations, not by memory bandwidth. This is the regime where the accumulator's issue rate binds. regime of GPU rooflineA model that plots achievable throughput against arithmetic intensity. Its ridge marks where a kernel flips from memory-bound to compute-bound. models. Because memory bandwidth is not the limiting factor, doubling instruction issue rates translates directly into throughput gains.
Precision Trade-Offs and Error Floor Bounds
Switching from FP32 to FP16 accumulation introduces small numerical truncation errors during intermediate dot-product summation. However, physical surrogate models, kernel regressions, and discrete PDE solvers already contain inherent discretization noise and input parameter uncertainty.
For well-conditioned physical operators (), the error floor introduced by FP16 accumulation remains bounded near relative error. If input data uncertainties exceed , using higher-precision accumulators consumes compute throughput without improving model accuracy.
Benchmark Results and Experimental Design
FP16 accumulation is enabled via PyTorch runtime options:
import torch
# Enable full-rate FP16 accumulation on Tensor Cores (PyTorch >= 2.7)
torch.backends.cuda.matmul.allow_fp16_accumulation = True
# Execute operator application GEMM
X = A_inv @ B
To isolate accumulator throughput gains from architectural changes, benchmarks were evaluated across three configurations on an NVIDIA RTX 3080 GPU (10 GB):
- CUDA Core FP32: Standard FP32 execution on general CUDA cores (TF32 disabled).
- Tensor Core FP32-Accumulate: FP16 input tensors with FP32 accumulator (cuBLAS baseline).
- Tensor Core FP16-Accumulate: FP16 input tensors with FP16 accumulator (optimized configuration).
Experimental isolation protocol
To prevent confounding variables during timing:
torch.manual_seed(0)
# Configuration 1: Pure FP32 (CUDA Cores)
torch.backends.cuda.matmul.allow_tf32 = False
X_fp32 = A_fp32 @ B_fp32
# Configuration 2: FP16 Inputs, FP32 Accumulator (Tensor Cores)
torch.backends.cuda.matmul.allow_fp16_accumulation = False
X_acc32 = A_fp16 @ B_fp16
# Configuration 3: FP16 Inputs, FP16 Accumulator (Tensor Cores)
torch.backends.cuda.matmul.allow_fp16_accumulation = True
X_acc16 = A_fp16 @ B_fp16Timings were captured using torch.cuda.Event metrics across 10 execution trials following warmup iterations.
Changing the accumulator precision yields a 1.91× speedup on matrix inversion applications and a 1.84× speedup on PDE Green’s function applications compared to matched FP16-input baselines.
Relative Latency Comparison
Disambiguating Cross-Path vs. Same-Kernel Speedups
Comparing FP16 accumulation directly against CUDA Core FP32 execution yields a nominal speedup of (). However, this metric combines two distinct architectural transitions:
- Moving computation from general CUDA cores to Tensor Cores (, a gain).
- Frictional accumulation rate doubling within Tensor Cores (, a gain).
To isolate the specific impact of the accumulator toggle, reported speedups ( and ) reflect comparisons against matched Tensor Core FP16-input baselines.
Impact of TF32 execution on baseline comparisons
If TF32 execution is enabled for FP32 inputs (allow_tf32 = True), baseline FP32 performance increases from to . This reduces the cross-path ratio while leaving the same-kernel FP16 accumulator speedup () unchanged.
Numerical Accuracy vs FP64 Gold References
To measure numerical precision loss, outputs from each execution mode were compared against double-precision (FP64) reference solutions () computed via torch.linalg.solve:
| Precision Mode | Accumulator Precision | Relative Error vs FP64 | Residual Norm ||AX - B|| / ||B|| |
|---|---|---|---|
| FP32 CUDA Cores | FP32 | 3.4 × 10⁻⁷ | 2.1 × 10⁻⁷ |
| TF32 Tensor Cores | FP32 | 1.2 × 10⁻⁴ | 8.9 × 10⁻⁵ |
| FP16 Tensor Cores | FP32 | 2.3 × 10⁻³ | 1.8 × 10⁻³ |
| FP16 Tensor Cores | FP16 | 3.4 × 10⁻³ | 2.6 × 10⁻³ |
Relative error is defined as ||X - X_gold|| / ||X_gold||. For physical surrogates with input noise > 10⁻³, FP16 accumulation provides maximum throughput without compromising effective accuracy.
Relative error and residual norms confirm that FP16 accumulation maintains numerical errors bounded between and for well-conditioned operators.
Why ill-conditioned operators require higher precision
Newton-Schulz matrix inversion iterations () require high precision during final residual corrections. In FP16 arithmetic, correction magnitudes drop below machine epsilon (), causing iterative updates to stall.
In contrast, shift-invert PDE operators () maintain bounded spectra, allowing FP16 accumulation to execute stably without convergence stalls.
Validity Boundaries and Condition Number Constraints
The application of FP16 accumulation is bounded by three specific numerical conditions:
- Condition Number Sensitivity: Test operators must remain well-conditioned. The PDE benchmark evaluates a screened PoissonThe operator I − α∇², a Poisson operator shifted away from singularity by a small α so its inverse stays well-conditioned. operator ( with ), yielding a condition numberHow much a matrix amplifies error when inverted. Near 1 is benign; a large value magnifies whatever the accumulator rounds off. . Unshifted Poisson operators () exhibit ill-conditioned spectra (), causing FP16 truncation errors to amplify significantly.
- Iterative Time-Stepping Accumulation: Explicit time-integration schemes (e.g., forward Euler PDE integration) compound rounding errors across sequential steps. FP16 accumulation should be restricted to single-pass matrix-vector applications or stationary solves.
- Residual Refinement Limits: Standard iterative refinement () fails to recover lost precision under FP16 accumulation because small residual updates round to zero within FP16 dynamic ranges.
Screened vs unshifted Poisson operator spectra
Unshifted Poisson operators contain near-zero eigenvalues, making the inverse operator highly sensitive to perturbations. Adding a screening parameter shifts the spectrum away from zero, enforcing and bounding condition numbers to .
Convergence mechanics of Newton-Schulz iterative refinement in FP16
Newton-Schulz matrix inversion iterations () require high precision during final residual corrections. In FP16 arithmetic, correction magnitudes drop below machine epsilon (), causing iterative updates to stall.
Verification and Reproducibility Protocol
All benchmark measurements adhere to the following experimental constraints:
- Reference Solves: Evaluated against FP64 reference ground truth (
torch.linalg.solve). - Timing Measurement: Captured using asynchronous GPU CUDA events (
torch.cuda.Event) across 10 trials (median reported). - Environment: NVIDIA RTX 3080 GPU (Ampere
sm_86, 10 GB), PyTorch 2.12, CUDA 13.0.
Generalization to Dense Matrix Operations Across Domains
The performance characteristics of FP16 accumulator execution extend to any compute-bound dense GEMM workload tolerant of relative error:
| Domain | Implementation Overhead | Throughput Speedup | Target Quality Metric |
|---|---|---|---|
| Dense Solves / PDE Green Functions | PyTorch runtime flag | 1.84–1.91× | Relative Error = 2.3e-3 vs FP64 |
| Vector Retrieval & Ranking | PyTorch runtime flag | 1.59× matmul | Recall@10 = 0.987 |
| Neural Radiance Field (NeRF) Rendering | Fused CUDA kernel + flag | 1.69–1.81× render | PSNR = 35.70 dB |
Across all three domains, enabling FP16 accumulation yields immediate throughput gains with negligible impact on domain-specific quality metrics.
Why sparse matrix multiplication receives no speedup from FP16 accumulators
In contrast to dense GEMMs, unstructured sparse matrix multiplication (SpMM) is memory-bandwidth bound (). Because compute units spend time waiting for HBM memory transfers, increasing Tensor Core accumulator issue rates yields no wall-clock latency reduction.
Conclusion
Enabling FP16 accumulation via PyTorch’s allow_fp16_accumulation option recovers 1.84–1.91× throughput on consumer NVIDIA Ampere GPUs for compute-bound dense matrix operations. For well-conditioned operators (), the resulting numerical error floor remains bounded at , providing significant acceleration for surrogate modeling, uncertainty quantification, and numerical PDE solves.
Glossary
Glossary — every term, defined
- Tensor cores
- Dedicated matrix-multiply units on NVIDIA GPUs. They multiply small fp16 input tiles and add up the products far faster than the general-purpose CUDA cores, which is why a dense GEMM belongs on them.
- CUDA cores
- The general-purpose arithmetic units on the GPU. They run the true-fp32 reference path and most memory-bound sparse work, both slower than the tensor cores on dense GEMM.
- MMA (matrix multiply-accumulate)
- The tensor-core primitive: multiply two input tiles and add the product into a running accumulator. A GEMM is built from many MMAs.
- Accumulator
- The running sum a matmul adds each product into. Its precision (fp16 or fp32) is chosen separately from the input precision, and it is the single knob this piece turns.
- fp16 / fp32 accumulation
- Summing the running dot product in half or single precision. On sm_86 GeForce the fp16 path issues at twice the rate of the fp32 path for identical fp16 inputs.
- GEMM
- General matrix-matrix multiply, the dense
C = A·Bkernel that every one of the four workloads reduces to. - cuBLAS
- NVIDIA's dense linear-algebra library and the GEMM backend PyTorch calls. It defaults to fp32 accumulation because that is correct on any input.
- Arithmetic intensity
- Floating-point operations per byte of memory traffic. The inverse apply sits near 1,400 ops/byte, which places it deep in the compute-bound regime.
- Roofline
- A model plotting achievable throughput against arithmetic intensity. Its ridge marks where a kernel flips from memory-bound to compute-bound.
- Compute-bound
- Limited by how fast the arithmetic units retire operations rather than by memory bandwidth. This is the regime where the accumulator issue rate binds and the lever lands.
- Condition number
- How much a matrix amplifies error when inverted. Near 1 is benign; a large value magnifies whatever the accumulator rounds off, which is why ill-conditioned operators leave the lever.
- Screened Poisson
- The operator
I − α∇², a Poisson operator shifted away from singularity by a small α=2e-3, giving cond ≈ 146 so its inverse stays well-conditioned. - The apply
- Applying a formed operator to a block of many right-hand sides. It is a large dense GEMM and the cost that repeats, as opposed to the one-time formation.
- fp64 gold
- A double-precision reference solve. Every rung is scored against it, so the fp32 and fp16 errors share one ground truth.
- TF32
- NVIDIA's reduced-precision tensor-core format for fp32-typed math. It is switched off for the reference so the baseline is a genuine CUDA-core fp32 path.