Files
263-0007-00L-Advanced-Syste…/docs/optimization_float_inlining_SoA_AVX2_polyexp_rsqrt.md
T
Linus Baumberger 9d8d63f1bf variant with rsqrt
2026-05-27 17:17:26 +02:00

2.6 KiB

Optimization: rsqrt + Newton, divide killed

  • Author: Linus
  • Predecessor: variant_float_inlining_SoA_AVX2_polyexp.cpp
  • File(s): variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp
  • Status: approx 10 to 20 percent faster

What this changes

We replace all three _mm256_sqrt_ps calls with _mm256_rsqrt_ps, which gives us 1/sqrt(x) directly. We then recover the sqrt itself with one extra multiply (sqrt(x) = x * rsqrt(x)) and reuse the inverses to rewrite the force scaling so that the final vdivps disappears. No Newton-Raphson refinement: we accept the ~12-bit precision of plain vrsqrtps since the verify tolerance is 1cm.

Code

See variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp. Asm has 3 vrsqrtps, 0 vsqrtps, 0 vdivps.

Benchmark

Conditions: N_ITER=1000, -O3 -march=native -flto, diff vs the polyexp predecessor.

x86

Machine: TBD

Frequency: TBD

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

ARM

no avx2 here

Analysis

The win comes primarily from killing the vdivps, not from the sqrt latency change. vdivps has 5-cycle throughput on port 0 (the divider port), and each j-block had exactly one of them in the force-scaling step. Removing it frees up port 0 for the three sqrts that also live there.

Replacing vsqrtps with vrsqrtps + multiply contributes a smaller piece: it shortens each sqrt from ~12 cycles latency to ~8, and the muls land on the FMA ports rather than port 0, so the divider port load drops further. The accuracy cost is ~12 bits of mantissa precision, which is well within the 1cm verify tolerance .

I also tried adding a Newton-Raphson refinement step to recover full sqrt precision. That variant ran slower than the pure-rsqrt version: the NR step adds 2 muls and one fnmadd on top of rsqrt, putting the recovered sqrt at ~20 cycles of latency, which is worse than vsqrtps's 12.

The speedup is consistent (~18-22% across all N), which suggests the divider port is on the j-block critical path at every problem size, not just at one particular working-set range.

Takeaway

probably not worth keeping. polyexp is faster on the perf machine at every size we measured.