Skip to content

finding: the mask-tail optimisation is inert on every power-of-two population, including the 4096-row tile - #316

Merged
AdaWorldAPI merged 3 commits into
masterfrom
claude/mask-tail-scope-finding
Sep 17, 2026
Merged

AdaWorldAPI merged 3 commits into
masterfrom
claude/mask-tail-scope-finding

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Blackboard only, no code. This is the gate on the 11-function tail rewrite #315 argued for — established by arithmetic before writing it, and it changes whether that rewrite is worth doing at all.

The arithmetic

A mask over n rows is ceil(n/64) words. The facade's algebra ops walk U64x8, so a tail exists only when words % 8 != 0. For a power of two, words = 2^(k-6), and 2^(k-6) % 8 == 0 for every k >= 9.

rows words tail tail share of the whole op
512 8 0 none
4096 64 0 none
10 000 157 5 73 %
65 536 1024 0 none
1 000 000 15 625 1 2.6 %
16 777 216 262 144 0 none

(share = a 16 ns padded tail against a body of groups × 0.31 ns, both from #315's own measurements)

Every power-of-two population at or above 512 rows has no tail at all — and this workspace's shapes are overwhelmingly powers of two: the 4096-row tile, the 64-word mask, the 512-byte node, the 4096-centroid codebook.

What this does to #315

#315 is not wrong. It is scoped narrower than it reads. Its sweep used base = 8 and base = 64 words — 512 and 4096 rows — plus k of 1..7, which is exactly the small end. Its "7 of 8 mask sizes have a tail" is a statement about arbitrary sizes, and consumer sizes are not arbitrary.

So the honest reading of the merged result:

  • "the padded tail is routinely larger than the work it trails" — true at 8–71 words, i.e. 512–4544 rows.
  • On a million-row table the same tail is 2.6 %.
  • On the canonical 4096-row tile it is 0 % — there is no tail to pay for.

Consequence: the rewrite is not justified yet, and I had the gate wrong

I told the reviewer on #315 that the rewrite should land behind a quieter machine. That was the wrong gate. The right one is a census of real consumer population sizes — which populations actually reach mask_and and friends, at what row counts. If they are powers of two the work is inert; if arbitrary row counts dominate it is worth ~2.6 % there and a lot at sizes like 10 000 rows.

Ternlog points the other way, independently

For mask_ternlog the padded form is one instruction — a full-width vpternlogq zmm over the zero-padded register. The fixed-step peel needs three logic ops at 4-lane plus more at 2-lane plus a scalar step. So for that site the padded tail may well be cheaper, which is the opposite of the direction #315 proposed, and is a second reason not to sweep all 11 sites uniformly.

What still stands from #315, unchanged

The codegen witnesses are untouched: U64x4 & really is bit-identical to a hand-written loop (the assembler merges the symbols), fixed-width peels really are packed on aarch64 as well as x86, and the avx512vl gate really is unnecessary because LLVM selects the tier itself. What is withdrawn is only the implied priority of acting on them.

The class

#315's five corrections were each a label outrunning its measurement. This one is a level up: a measurement outrunning its regime. The numbers were right at the sizes probed and the conclusion was stated without them. The cheapest way to catch that is arithmetic on the size formula, not another benchmark.


Update: the census this PR called for is now run, and it CLOSES step (b)

Pushed in 483b7c1e. Read-only against lance-graph-java's lgj-abi, the binding consumer of the facade's mask algebra.

1. There is no tiling of the population. lgj_pattern_open(n_rows, …) / lgj_rowstore_open(n_rows, …) take the row count directly, and a mask spans the whole population (abi.rs::mask_words_for = n_rows.div_ceil(64)). The only "tile" in that crate is the 12-byte facet register, not the rows. So the padded tail is paid once per op and amortizes over the entire body — the favourable direction for the status quo.

2. Every committed population size is blind to the tail, bimodally:

rows words can it see a tail?
4, 8, 10, 16, 32, 64 1 all tail — not one full group
70, 100, 128 2 all tail
200 4 all tail
500 8 none
1000, 1024 16 none
4096 64 none
64000 1000 none

The small ones are correctness fixtures where the op is its tail and speed is irrelevant; every size large enough to have a body has zero tail. No committed test or bench in the consumer can exercise the regime the optimisation targets — which is precisely why #315's probe had to choose base = 8 and 64 words to see it at all.

3. Where it does bite (16 ns tail, 0.31 ns/group): 85 % at 5 k rows, 35 % at 50 k, 21 % at 100 k, 5 % at ~502 k, 2.6 % at 1 M, 1 % at ~2.6 M, and 0 % on every power of two ≥ 512.

Verdict: step (b) is closed as measured-not-worth-doing, not deferred

It would touch a hot facade at 11 sites across six realizations to win something only for arbitrary populations in roughly the 5 k – 500 k row band — and it would make mask_ternlog worse, since its padded form is one full-width vpternlogq where the peel needs three ops plus more.

Reopening it needs a named consumer workload whose populations sit in that band. Not another kernel benchmark.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv


Generated by Claude Code

… population

Established before writing the rewrite #315 argued for, because it changes
whether that rewrite is worth doing. No code — this entry is the gate.

A mask over n rows is ceil(n/64) words, and the facade's algebra ops walk
U64x8, so a tail exists only when words % 8 != 0. For a power of two,
words = 2^(k-6), which is divisible by 8 for every k >= 9. Measured against a
16 ns padded tail and a 0.31 ns/group body:

  512 rows        8 words   no tail
  4096 rows      64 words   no tail      <- the canonical tile
  10 000 rows   157 words   5-word tail, 73% of the op
  65 536 rows  1024 words   no tail
  1 000 000     15625 w     1-word tail, 2.6% of the op
  16 777 216   262144 w     no tail

So every power-of-two population at or above 512 rows has NO TAIL AT ALL, and
this workspace's shapes are overwhelmingly powers of two: the 4096-row tile,
the 64-word mask, the 512-byte node, the 4096-centroid codebook.

#315's measurement is not wrong, it is scoped narrower than it reads. The sweep
used base = 8 and 64 WORDS — 512 and 4096 rows — so "the padded tail is
routinely larger than the work it trails" holds at 8-71 words and becomes 2.6%
on a million-row table and 0% on the canonical tile. Its "7 of 8 mask sizes
have a tail" is a statement about arbitrary sizes; consumer sizes are not
arbitrary.

Consequence: the 11-function rewrite is not justified yet, and the gate is NOT
"a quieter machine" as I told the reviewer on #315 — it is a census of real
consumer population sizes. Ternlog points the other way independently: its
padded form is ONE full-width vpternlogq where the fixed-step peel needs three
logic ops plus more, so a uniform sweep of all 11 sites would make that site
worse.

The class: #315's corrections were each a label outrunning its measurement.
This is one level up — a measurement outrunning its REGIME. The numbers were
right at the sizes probed and the conclusion was stated without them. Arithmetic
on the size formula answers it faster than another benchmark.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 15 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available. Your 56 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 365ffc60-9e97-4616-8e84-155cd853f27d

📥 Commits

Reviewing files that changed from the base of the PR and between b27b36c and 9b3dd5b.

📒 Files selected for processing (1)
  • .claude/blackboard.md

Comment @coderabbitai help to get the list of available commands.

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review September 16, 2026 23:47
…ferred

(18) named a census of real consumer population sizes as the gate. Run it,
read-only, against lgj-abi — the binding consumer of the facade's mask algebra.

1. There is NO tiling of the population. `lgj_pattern_open(n_rows, ...)` takes
   the row count directly and a mask spans the whole population; the only
   "tile" in that crate is the 12-byte facet register, not the rows. So the
   padded tail is paid once per op and amortizes over the entire body — the
   favourable direction for the status quo.

2. Every committed population size is blind to the tail, bimodally: 4..200 rows
   are 1-4 words, i.e. ALL TAIL with not one full group (correctness fixtures
   where speed is irrelevant), while 500 / 1000 / 1024 / 4096 / 64000 rows are
   8 / 16 / 16 / 64 / 1000 words — every one divisible by 8, so ZERO tail. No
   committed test or bench can exercise the regime the optimisation targets,
   which is why #315's probe had to pick base = 8 and 64 words to see it.

3. Where it bites, as a share of the op: 85% at 5k rows, 35% at 50k, 21% at
   100k, 5% at ~502k, 2.6% at 1M, 1% at ~2.6M, and exactly 0% on every power
   of two at or above 512.

Verdict: step (b) is closed as measured-not-worth-doing rather than deferred.
It would touch a hot facade at 11 sites across six realizations to win
something only for arbitrary populations in the ~5k-500k band, and would make
`mask_ternlog` worse — its padded form is one full-width vpternlogq where the
peel needs three ops plus more. Reopening it needs a named consumer workload
whose populations sit in that band, not another kernel benchmark.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70ee86b3d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/blackboard.md Outdated
Comment thread .claude/blackboard.md
…ot a win

Two codex findings on #316, both correct, both against this entry.

(a) The headline read "inert on every power-of-two population". False below 512
    rows: 64/128/256 rows are 1/2/4 words, so words % 8 != 0 and the tail is the
    WHOLE op. The derivation immediately above the table says k >= 9 and the
    prose below said "at or above 512 rows" — the TITLE is what lost it. That is
    the fourth level of this session's one defect class: after a label
    outrunning its accumulator, a claim outrunning its evidence, and a
    measurement outrunning its regime, a headline outrunning the derivation
    directly beneath it.

(b) A SHARE is not a WIN. The 16 ns is the padded tail's share of the current
    op; the rewrite does not remove it, it replaces it with #315's measured
    fixed-step tail of 5.33 ns. Every share figure therefore overstated the win
    by exactly 16 / 10.67 = 1.5x. At a million rows: current 1953 x 0.31 + 16 =
    621 ns, win 10.67 ns = 1.7%, not 2.6%.

Both tables now carry share AND win columns, and the crossovers move in: the win
falls under 5% above ~325k rows and under 1% above ~1.74M, where the share put
those at ~502k and ~2.6M. The verdict is unchanged and strengthened — the band
where the work pays is narrower than the entry first claimed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
@AdaWorldAPI
AdaWorldAPI merged commit 6f40bc6 into master Sep 17, 2026
20 checks 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.

2 participants