Skip to content

Commit c10029b

Browse files
committed
hop_cached_vs_gather: the scatter is O(N/64 + selected bits) per facet, not O(frontier)
CodeRabbit on #79: scatter walks every word of selected before visiting set bits — 1 024 words per facet at 65 536 rows regardless of frontier size. Doc and board entry corrected; implementation unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
1 parent 7e5cfdf commit c10029b

2 files changed

Lines changed: 9 additions & 4 deletions

File tree

‎.claude/board/LATEST_STATE.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ Cache build: **843–930 µs**.
3030
- **The tile pays for itself on the second hop at every frontier.** A store
3131
generation's predicates do not change between hops; the shipped body
3232
re-derives them with 64 contiguous 256 KiB passes per hop. With the tile,
33-
what is left is ≤ 5 µs of `mask_and` plus the scatter, which is O(frontier)
34-
and the whole cost above ~1 %.
33+
what is left is ≤ 5 µs of `mask_and` plus the scatter, which is
34+
`O(N/64 + selected bits)` per facet (it walks every word of `selected`
35+
before knowing which are empty — CodeRabbit on #79 corrected an
36+
"O(frontier)" claim here) and the whole cost above ~1 %.
3537
- **Not measured here:** invalidation (a write to any classid/hi32 lane of the
3638
generation drops all 32 masks — the registry already does this wholesale for
3739
`cached_carving`), and the cache multiplies by the number of edge classes

‎native/lgj-abi/examples/hop_cached_vs_gather.rs‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@
3636
//! hops at every frontier): a store generation's predicates do not change
3737
//! between hops, and the shipped body re-derives them with 64 contiguous
3838
//! 256 KiB passes per hop. What remains per hop is one 8 KiB `mask_and` per
39-
//! facet (≤ 5 µs) plus the scatter, which is O(frontier) and is the whole
40-
//! cost above ~1 %.
39+
//! facet (≤ 5 µs) plus the scatter, which is `O(N/64 + selected bits)` per
40+
//! facet — it walks every word of `selected` before it can know which are
41+
//! empty (the same word-walk floor `ternlogq_sparse_reapply_probe` measured,
42+
//! ~360 ns at 1 024 words), then one payload read per set bit — and is the
43+
//! whole cost above ~1 %.
4144
//!
4245
//! The `gather` column is NOT a competitor to the mask (R1 ruled the
4346
//! population serialization out); it is the baseline for the *access shape*

0 commit comments

Comments
 (0)