Skip to content

v0.4.1 — application performance: two loop shapes

Latest

Choose a tag to compare

@vukics vukics released this 04 Nov 09:27
· 5 commits to main since this release

No breaking changes. Applying a MultiDiagonal is faster, and its speed depends far less on where the arrays lie in memory. Results agree with v0.4.0 up to rounding: within a row, the order of summation differs.

Performance: the application loop was rewritten in three steps. Addresses are computed once per diagonal, and a loop nest generated at compile time runs in memory order, axis 0 innermost (#1). The complex multiply-add is done in real arithmetic, so the default build is as fast as with -fcx-limited-range, and an axis 0 of up to four elements (a qubit) is unrolled at compile time (#23). For long axes, operands larger than cache and strided views, the diagonals contributing to a row are summed before one store, so the state is swept once instead of once per diagonal (#1, #25). On the reference machine (i7-7700, GCC 16, Eigen 5.0.1), application is now 2.7–3.6× faster than Eigen's sparse product in cache at rank 1 and with the mode on axis 0, 1.4–2.2× with a qubit on axis 0, and 1.4–2.5× out of cache except with a qubit on axis 0 (0.6–0.9×). At v0.4.0, multi-axis application was 3.4–4.5× slower than Eigen. Where the array placement still matters, in small views, the shape used is faster at any placement than the alternative (#25).

New API: applyByDiagonals and applyByRows, the two loop shapes that operator() chooses between from the view's strides and extents. They are public, so that tests and benchmarks can force either.

Benchmarks: kernels.cc gains case F, where the two shapes cross over, and case G, the placement scan of #25. The performance page (benchmarks/performance.md) records every figure as a median over five processes on a quiet reference machine, together with what remains: a qubit on axis 0 of a state larger than cache, and contiguous slices of power-of-two length out of cache (#1). CI builds the benchmarks without -march=native, which failed with Clang 18 on runners with AVX10.