Skip to content

Columnar execution core (opt-in) + the batch-size scaling report (TASK-61) - #48

Closed
claude-agent-ahrzb[bot] wants to merge 7 commits into
masterfrom
task-61-columnar-core
Closed

Columnar execution core (opt-in) + the batch-size scaling report (TASK-61)#48
claude-agent-ahrzb[bot] wants to merge 7 commits into
masterfrom
task-61-columnar-core

Conversation

@claude-agent-ahrzb

Copy link
Copy Markdown

The final approved-roadmap item. Two deliverables:

The columnar core (exec/columnar.rs, +1942 lines)

Mask-based vectorization of the existing IR — blocks in topo order with active-row masks, block-param merges under edge masks, all 37 instruction kernels, exact trap ROW-ORDER parity with the row loop (a late-instruction trap on an early row beats an early-instruction trap on a later row — tested), stage-B multiplicity cleanly rejected to the row path. Verified: 500-seed interp-vs-columnar differential (outputs + traps identical, zero rejects), the five IR fixtures, and the python infer_arrow == infer_rows suite through the core on every serving scenario. cargo 177 / pytest 622 + 13 xfail.

The measured verdict — and honest wiring

The v1 core computes at row-core parity (kernels call the same scalar helpers per row): house_prices ~1.35× better, titanic/fraud ≈ tie, store_sales behind, and a per-call lane-allocation cost that hurts small batches. Defaulting it on would regress, so it ships opt-in (SPECIALIZER_COLUMNAR=1); fn.arrow_backend reports the active engine. The identified next lever is true vectorized kernels + lane reuse — compute, not boundary.

The scaling report

scripts/bench_scaling.py swept four engines × four scenarios × n = 1 → 262,144 (benchmarks/scaling_results.json); scripts/render_scaling_svg.py renders the log-log per-row plot dependency-free. Report artifact (the deliverable): https://claude.ai/code/artifact/40dbeb1c-f102-489e-9e65-d57d48385846 — regime map: serving calls (1–1k rows) are ours by 2–3 orders of magnitude; DuckDB takes over at ~4–16k rows/call; the middle band is within ~1.5×.

🤖 Generated with Claude Code

ahrzb and others added 7 commits July 28, 2026 05:23
…g report)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ckend (TASK-61)

Mask-based vectorization of the acyclic CFG over the existing IR: SSA
values become full-batch lanes, blocks run in topo order with per-block
active masks, edges merge branch args into param lanes, and outputs stage
full-batch then gather in row order. Every kernel calls the interpreter's
shared duck_*/window/casemap helpers, so semantics match bit for bit.

Traps replicate the row loop exactly: a trapping row records its first
message and deactivates; the smallest trapping row's message surfaces.

Stage-B multiplicity (emit.to, multimap/batchmap, probe.range/probe.read,
CFG cycles) is rejected at compile with a clear message — row-path-only.

Tests: the five IR fixtures against the interp expectations (incl. the
CASTS trap), a 500-seed interp-vs-columnar differential (outputs, emitted
counts, traps; zero rejects), a row-order-beats-instruction-order trap
test, a masked-row safety test, and the MULTI_EXPAND rejection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…(TASK-61)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nd getter (TASK-61)

The batch core compiles alongside the row backend from the same program
(fresh statics materialization); a rejection (stage-B multiplicity,
cycles) just means infer_arrow keeps the row fn. The existing
infer_arrow == infer_rows differential suite now exercises the columnar
core on every serving scenario — parity by construction, all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ap finale (TASK-61)

The v1 batch core measured at row-core parity on compute (its kernels
call the same scalar helpers per row) with a per-call allocation cost
that hurts tiny batches: house_prices ~1.35x better, titanic/fraud ~tie,
store_sales behind. Honest wiring: OPT-IN via SPECIALIZER_COLUMNAR=1 —
no default regression; the core ships as the verified foundation (500-
seed differential, trap-row-order parity) for true vectorized kernels,
the identified next lever. Python differential under the flag covers
all scenarios; benchmarks/scaling_results.json carries the four-engine
sweep (1..262144 rows) behind the report's log-log plot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude-agent-ahrzb

Copy link
Copy Markdown
Author

Closed by decision, not by defect: the measured v1 core sits at row-core compute parity, and columnar execution above the serving regime is better served by DuckDB — we're strong before ~5k rows/call and that's the battle we're choosing. Work preserved on task-61-columnar-core / task-61-columnar-exec (all gates were green) if we ever come back to it. The scaling report that motivated the decision: https://claude.ai/code/artifact/40dbeb1c-f102-489e-9e65-d57d48385846

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