Files
263-0007-00L-Advanced-Syste…/docs/optimization_float_inlining_SoA_AVX2_polyexp.md
T

2.5 KiB

Optimization: SIMD polynomial exp (float, 8-wide) + FTZ/DAZ

  • Author: Linus
  • Predecessor: variant_float_inlining_SoA_AVX2.cpp
  • File(s): variants/variant_float_inlining_SoA_AVX2_polyexp.cpp, main-float.cpp (FTZ/DAZ enable)
  • Status: TBD, positive locally (approx twice as fast)

What this changes

The 8 scalar expf calls in the j-loop become a single SIMD polynomial approximation exp256_ps that operates on __m256. Range-reduce x = n*ln2 + r with n = round(x/ln2), evaluate a degree-5 Horner polynomial for exp(r) on r in [-ln2/2, ln2/2], then scale by 2^n via the Schraudolph bit-trick on the IEEE 754 exponent slot (shift the biased exponent by 23). Degree-5 is enough for float, the polynomial is good to ~1e-5 absolute on the reduced range, well under the 1cm verify tolerance.

main-float.cpp also gets two MXCSR writes at the top of main():

_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);

This was the part that actually mattered, see Analysis.

Code (relevant snippet)

See variants/variant_float_inlining_SoA_AVX2_polyexp.cpp for the full j-loop and main-float.cpp for the FTZ/DAZ setup.

Benchmark

Conditions: min of N runs (TBD), N_ITER=1000, -O3 -march=native -flto. Diff is vs variant_float_inlining_SoA_AVX2.

x86

Machine: TBD

Frequency: TBD

N W(n) [Flops] T(n) [Cycles] Performance [Flops/Cycle] Diff vs Predecessor
50
100
200
500

ARM (Apple)

Not applicable, AVX2-only. A NEON port would need its own vectorised exp.

Analysis

roughly twice as fast

Takeaway

Polyexp helps as expected. The real fix is FTZ/DAZ in main-float.cpp, without it everything downstream in the float chain is silently subnormal-stalled

References