Scalar Emulation in cuEST#
Modern NVIDIA GPUs deliver over 100 TFLOPS of FP32 scalar throughput on architectures
such as RTX Pro 6000 Blackwell, far exceeding their native FP64 scalar rates.
For compute kernels that can be expressed as large matrix multiplications,
GEMM-based emulation via the Ozaki scheme
already provides a highly effective path to this FP32 throughput. However, many cuEST
compute routines—most notably the Polarizable Continuum Model (PCM) solvent kernels
and the VV10 nonlocal correlation functional—involve irregular, custom CUDA kernels
with per-thread reductions that cannot be reformulated as GEMMs. For these kernels,
cuEST uses scalar emulation based on float-float (ffloat) arithmetic: a
software-emulated extended-precision data type built from a pair of FP32 values that
recovers near-double precision while operating entirely on FP32 hardware.
Note
Float-float is not IEEE 754 FP64. It provides approximately 14 decimal digits of precision (vs. 16 for FP64) and does not extend the FP32 dynamic range. Values near \(10^{-38}\) or \(10^{38}\) should be treated with care. See Accuracy Considerations and Limitations for details. The quantities computed by cuEST float-float kernels are not expected to be sensitive to the reduced dynamic range, and 14 effective digits of precision are considered sufficient for the target quantum chemical quantities. Users are encouraged to validate these assumptions against their own application requirements.
Note
The use of float-float compute in certain functions may require JIT compilation (see Just-In-Time (JIT) Compilation in cuEST). Consult the C API reference to determine whether a given routine’s kernels are JIT-compiled. For those that are, because the float-float code path is more complex than the equivalent native-FP64 kernel, its first-call (cold-cache) JIT compilation can be 2-3x slower than the double-precision path, and can take up to about a minute for some tasks. This cost is paid once per machine and reused via the on-disk kernel cache; it does not recur on subsequent calls or subsequent runs.
Float-Float Arithmetic#
The float-float data type represents a scalar value \(x\) as an unevaluated sum of two single-precision components,
where \(x_{\mathrm{hi}}\) stores the leading significant bits and \(x_{\mathrm{lo}}\) stores the rounding error of \(x_{\mathrm{hi}}\), with the normalization condition \(|x_{\mathrm{lo}}| \leq \tfrac{1}{2}\,\mathrm{ulp}(x_{\mathrm{hi}})\). Together, the two FP32 words recover roughly 45–48 bits of mantissa — just short of the 53-bit mantissa of IEEE FP64. Because each component remains an FP32 value, the exponent range does not change.
Table 1 — Numerical properties of floating-point types
Type |
Mantissa |
Exponent |
Range |
Digits |
|---|---|---|---|---|
|
53 bits |
11 bits |
\({\sim} 10^{-308}\ \text{–}\ 10^{308}\) |
~16 |
|
24 bits |
8 bits |
\({\sim} 10^{-38}\ \text{–}\ 10^{38}\) |
~7 |
float-float |
45–48 bits |
8 bits |
\({\sim} 10^{-38}\ \text{–}\ 10^{38}\) |
~14 |
Arithmetic operations are performed entirely in FP32, so performance is determined by the device’s FP32 throughput rather than its FP64 throughput.
Controlling Float-Float Emulation#
High-level control of float-float compute paths is governed by the same cuestMathMode_t that
controls Ozaki-based emulation. To disable float-float (and all other emulated or mixed-precision
paths) and force native FP64 arithmetic throughout, set the math mode to CUEST_NATIVE_FP64_MATH_MODE.
The CUEST_NATIVE_FP64_MATH_MODE takes precedence over other options controlling emulation and
mixed-precision compute. To allow float-float compute paths to be used, use the CUEST_DEFAULT_MATH_MODE.
When CUEST_DEFAULT_MATH_MODE is set, control over the use of float-float paths is handled on
a per-function basis.
Functions capable of using a float-float compute path take a cuestFfloatUsageMode_t parameter.
When this parameter is set to CUEST_FFLOAT_USAGE_MODE_DEFAULT, the decision of whether or
not to use the float-float compute path is based on the current GPU compute capability and
if using float-float is expected to provide a performance advantage. In cases where JIT-compiled
kernels are required to use float-float compute and they are not available, the native FP64 path will
be used when CUEST_FFLOAT_USAGE_MODE_DEFAULT is set. To activate the float-float code path,
CUEST_FFLOAT_USAGE_MODE_ON can be set. If CUEST_FFLOAT_USAGE_MODE_ON is set and JIT-compiled
kernels required for the float-float code path are not available, an error status will be returned.
The use of float-float compute can be disabled on a per-function basis by setting CUEST_FFLOAT_USAGE_MODE_OFF.
See also
GEMM-based Emulation in cuEST for a description of Ozaki-based emulation (density-fitted exchange), which complements float-float by accelerating GEMM-dominant compute paths via fixed-point arithmetic.
Accuracy Considerations and Limitations#
Float-float is an attractive performance–accuracy compromise for a wide class of custom kernels, but users and integrators should be aware of the following inherent limitations:
- Reduced precision.
Float-float provides ~14 decimal digits, not 16. For most quantum chemistry observables (energies, forces, properties), this is well within the accuracy of the underlying molecular model. By default, cuEST enables float-float only on GPUs where it is expected to provide a performance advantage (it remains disabled on devices with high native FP64 throughput: compute capabilities 8.0, 9.0, and 10.0), and the float-float paths have been validated across a broad range of molecular systems, basis sets, and dielectric media.
- No exponent range extension.
Each FP32 component has an 8-bit exponent. The dynamic range is approximately \(10^{-38}\) to \(10^{38}\) — far narrower than FP64’s \(10^{-308}\) to \(10^{308}\). Quantities involving physical constants near the float underflow boundary (e.g., \(\hbar \approx 10^{-34}\) J·s in SI units) are not suitable for float-float without appropriate rescaling.
- Validation in cuEST.
The cuEST float-float kernels have been characterized across representative molecule sizes, basis sets, and convergence tolerances, and are considered suitable for the target quantum chemical quantities. Users are nonetheless advised to verify this holds for their own systems by checking a representative set of end-to-end results.