Perf pass 2: benchmark the uncovered operation surface, then fix what it exposed#21
Merged
Conversation
New nanobench groups for operations that had no row at all: binary sub (u8 / signed / Q8.8), mod, unary negation, compound -= / *= / += rational, min/max (same + mixed grid), midpoint, lerp, cross, add_all/mul_all, wrap_cast, sentinel stores, comparison == (incl. bound vs raw scalar), conversions out of bound, f64-backed add/mul, the exact/rational path (exact-backed add/mul/div/compare, mixed exact + integer add, and detail::rational engine ops vs a hand-rolled reduced int64 fraction), bound_range iteration, and cmath ceil/atan/acos/sinh/log10/pown/pow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
operator* built Lower + index*Notch in rational and ran the full assignment engine for every element. Index storage now returns the iterator index as the raw directly (it stays in [0, NotchCount]; the sentinel slot is a numeric_limits extreme outside that span), and integer-grid value storage decodes with one multiply-add; the start ctor inverts the same mapping. Single-step ++/-- wrap by compare instead of paying the euclidean mod's two divides. Rational and fp raws keep the generic path. Bench: 1286 -> 146 ins/op (integer grid), 1609 -> 145 (1/256 grid). Guards: decode-equality across every storage kind + dispatch pins in test_range.cpp ([perf-paths]). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-= delegated to += (-rhs), but negation shifts an index-raw operand's Lower and defeats both += fast paths, sending Q8.8-style grids through the full binary add + cross-grid assign. With equal notches the raw difference is exact up to a compile-time bias (Lower<R>/Notch for an index-raw rhs), reusing apply_raw_overflow for the policy tail. Bench: Q8.8 -= 806 -> 468 ins/op (the residue is operand construction). The new fallback test exposed a latent bug: the boundable-rhs store used the notch-index machinery for rational-raw TARGETS, rounding an index-raw source's value to a whole number (7/3 -> 2/1) and applying the grid transform to an exact source's raw that already was the value (5/3 -> corrupted). rational targets now snap the decoded source value through the rational-rhs store. Regression cases in test_cross_grid. Also: Q-format vs integral-scalar ==/<=> compare as cross-multiplied integers ((bias + raw)*n vs c*d, exact both ways) when both terms provably fit imax for every value of the scalar type; 64-bit scalars with large denominators fall back to the rational decode. Bench: Q8.8 == int 677 -> 139 ins/op (native parity). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New call-free kernels: bnd_perf_sub_compound (Q8.8 -=), bnd_perf_fp_add (f64-backed add lowers to one addsd — proven parity; the bench row's 2x is loop-harness noise), bnd_perf_range_sum (both bound_range decode arms). docs/performance.md regenerated with the new groups; amalgamation refreshed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-up to #18/#19/#20: the bench had no rows at all for sub, mod, negation, compound `-=`/`*=`, min/max/midpoint/lerp/cross, wrap_cast, sentinel stores, `==`, conversions out, f64-backed arithmetic, the exact/rational path, `bound_range` iteration, and several `bnd::math` functions. This PR adds ~30 rows covering all of that, then optimizes the three paths the new rows proved slow — and fixes a correctness bug the new tests flushed out.
Measured wins (ins/op, GCC -O3)
Correctness fix (latent bug found by the new fallback tests)
Cross-grid assignment onto a rational-raw target used the notch-index machinery: an index-raw source's value was rounded to a whole number (7/3 → 2/1) and a rational-raw source's raw — already the value — had the grid transform applied again (5/3 → corrupted `3/-1`). Reproduces on main; rational targets now snap the decoded source value through the rational-rhs store. Regression cases in test_cross_grid.
Guards
Verification
🤖 Generated with Claude Code