Skip to content

mad_scaler: O(log w) MAD selection and a ring-buffer sorted window, 4… - #11

Merged
MathisWellmann merged 1 commit into
mainfrom
performance
Oct 6, 2026
Merged

MathisWellmann merged 1 commit into
mainfrom
performance

Conversation

@MathisWellmann

@MathisWellmann MathisWellmann commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

….6x-150x faster

Every update merged all w absolute deviations into a buffer to read the middle one or two, and kept the sorted window in a Vec whose insert/remove shifted ~w values. Both made an update O(w): at w = 8192 about 21 us, which dominated the feature extraction of the agent-symbiont runners (92 us per trade for 9 MadScalers).

  • The MAD is now selected, not merged: the deviations form two non-decreasing sequences left and right of the median, and the (n/2)-th smallest of their union is found by a binary search over the split, computing only ~2 log2(w) deviations.
  • The sorted window is a VecDeque: insert/remove move only the shorter side, so monotone input (timestamps) slides without moving anything and other input moves at most w/2 values.

The output is bit-identical: every deviation uses the same expression and an order statistic does not depend on tie order. New tests check that against an oracle that sorts the window and its deviations from scratch, comparing integer_decode() exactly for f64 and f32 over windows 1..=10, 16, 31, 32, 63, 64, 255, 256 and streams with ties, a zero MAD, monotone input and outliers. The oracle passed on the old implementation before the change, and catches mutated selections (max for min, inverted search predicate, wrong rank).

benches/mad_scaler (100k realistic prices, vs the previous commit): w=128 47 -> 10 ms (4.6x), w=1024 285 -> 13 ms (21x), w=8192 2103 -> 28 ms (75x), w=32768 5468 -> 77 ms (71x) for f64; f32 up to 150x.

2026-10-06-134333_hyprshot

….6x-150x faster

Every update merged all w absolute deviations into a buffer to read the
middle one or two, and kept the sorted window in a Vec whose
insert/remove shifted ~w values. Both made an update O(w): at w = 8192
about 21 us, which dominated the feature extraction of the
agent-symbiont runners (92 us per trade for 9 MadScalers).

- The MAD is now selected, not merged: the deviations form two
  non-decreasing sequences left and right of the median, and the
  (n/2)-th smallest of their union is found by a binary search over the
  split, computing only ~2 log2(w) deviations.
- The sorted window is a VecDeque: insert/remove move only the shorter
  side, so monotone input (timestamps) slides without moving anything
  and other input moves at most w/2 values.

The output is bit-identical: every deviation uses the same expression
and an order statistic does not depend on tie order. New tests check
that against an oracle that sorts the window and its deviations from
scratch, comparing integer_decode() exactly for f64 and f32 over
windows 1..=10, 16, 31, 32, 63, 64, 255, 256 and streams with ties, a
zero MAD, monotone input and outliers. The oracle passed on the old
implementation before the change, and catches mutated selections
(max for min, inverted search predicate, wrong rank).

benches/mad_scaler (100k realistic prices, vs the previous commit):
w=128 47 -> 10 ms (4.6x), w=1024 285 -> 13 ms (21x), w=8192 2103 -> 28
ms (75x), w=32768 5468 -> 77 ms (71x) for f64; f32 up to 150x.

End to end in nexus (feature_day bench, one real BTCUSDT day, 18
production extractors): pipeline 121 -> 2.0 CPU-s per day, sequential
22.8 -> 0.51 CPU-s per day, same feature digest.
@MathisWellmann MathisWellmann self-assigned this Oct 6, 2026
@MathisWellmann
MathisWellmann merged commit 86b9bf4 into main Oct 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant