Repository navigation
cost: extrapolate WidthCosts linearly above the largest anchor; variable anchors (#6 stage 1); threadteam 0.1.1 - #7
Merged
Conversation
…age 1) `WidthCosts` no longer holds a table of widths 1..=6 with the width-6 value held flat above it. It stores the measured anchors (widths and nanoseconds, at most `MAX_ANCHORS` = 12) and evaluates the model per lookup: * below the first anchor: the first value, between two anchors: linear interpolation as before (i128, clamp at 0), above the largest anchor `w_m`: `ns[w_m] * w / w_m` in u128, saturating at `u64::MAX`. A wide section is never charged the cost of the largest anchor, so `width_for` no longer answers the full width just because the width-6 section pays. * `from_anchors(&[(usize, Duration)]) -> Option<Self>` adds measured anchors up to `u16::MAX` (const, allocation-free, no panic); `new` and `flat` keep their signatures and their 2/4/6 anchors. `min()` is the minimum over the anchors, which is the minimum over all widths. * `for_class(X86_64Avx512)` gains the measured width-8 team anchor 0.98 us from the post-fix run; in pool and outside keep 2/4/6 (their width-8 values are pre-fix data). Values at widths 1..=6 of every existing row are unchanged and pinned in a test; the generic row keeps 3/15/40 us at the anchors and now grows above them. Unit tests cover the flat-row law (1 us at 6/12/24/48), non-decreasing and at-least-linear extrapolation, anchors up to 64, `from_anchors` rejections and const use, equality ignoring unused capacity, a `Duration::MAX` row, and `width_for_by(24 us, 1, 64)` = 12 on a 1-us row. `benches/cost_lookup.rs` gains a budget-64 `width_for_by`, `min_cost`, a by-value `DispatchCosts` copy and the team-token `Exec` queries; the design records and the README state the new contract and keep the historical reason for the earlier flat model.
The 128-bit division is a library call; the 64-bit one gives the same truncated value whenever the product fits. Lookup at widths 2..8: 7.35 -> 4.12 ns (base table index 0.89 ns). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on test) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anchor; variable anchors) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 29, 2026
WidthCosts is flat above width 6: extrapolate conservatively and accept measured anchors up to 64
#6
Closed
Merged
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.
Part of #6 (stage 1: proposals 1 and 2). Stage 2 (the broccoli Zen2 row from tensor4all/faer#91) and the faer migration come in separate PRs.
Summary
w_m,WidthCosts::at(w)iscost(w_m) * w / w_m(saturating) instead of the flatcost(6). A region that does not pay at 6 therefore does not pay at 64.WidthCosts::from_anchors(&[(width, Duration)]) -> Option<Self>takes up toWidthCosts::MAX_ANCHORS(12) strictly increasing anchors with widths from 2 tou16::MAX.const(usable in aconstitem), allocation-free, and never panics.Nonefor empty input, too many anchors, a width below 2, or widths that are not strictly increasing.new([2, 4, 6])andflatkeep their signatures.WidthCostsnow stores its anchors (widthsu16, nsu64, length) and interpolates at lookup, with a 64-bit fast path that falls back to 128 bits only when a product overflows.DispatchCostsabout 1.5 KB.TeamExecand faer copy it by value.docs/design/thresholds.md). Without it the extrapolation would charge 1.2 us at width 8 on the measured 8-thread host.WidthCosts,for_class, README,docs/design/placement.mdanddocs/design/thresholds.mdnow describe the new contract. The thresholds doc keeps one historical note on why the model was flat before.Done-when checks (from #6)
w_mthe row is non-decreasing and at least linear, checked on five rows.width_for_by(24 us, 1, budget 64)picks 12 on the 1-us row, and a large enough estimate picks 64.from_anchorsrejects invalid input and works in aconst.Duration::MAXrow never pays.tests/dispatch_cost.rsnow expects the extrapolated values instead of the flat ones.tests/alloc_free.rsandtests/team_alloc_free.rspass.Lookup cost
Measured with
benches/cost_lookup.rs, extended in this PR. Same bench file on basef29c8ceand on this branch,taskset -c 56-59on primerose, best of 9 x 2M calls, ns per call:at(widths 2..8)payswidth_forbudget 8width_forbudget 64min_costDispatchCostsExec::dispatch_cost(team)Exec::width_for(budget 8)size_of:WidthCosts48 -> 128 B,DispatchCosts144 -> 384 B. The extra cost is far below one section, which the rows charge at 0.6 us or more.Verification
The AGENTS.md pre-push checklist passes locally:
cargo fmt --checkcargo clippy --all-targets --all-featuresand--no-default-features, both with-D warningscargo test,--all-featuresand--no-default-featuresRUSTFLAGS="--cfg loom" cargo test --release --test loom_park(the park/wake core is untouched)cargo deny check bansscripts/check-no-public-rayon.shcargo doc --no-depsIndependent pre- and post-implementation reviews (gpt-6.1-sol) were done. The post-review had no BLOCKER or IMPORTANT findings, and its minor ones are fixed.
Downstream
tensor4all/faer mirrors the flat model for InPool and Outside and asserts equality with threadteam through width 12. Those assertions change when faer moves to 0.1.1, which is the stage-4 PR that also deletes
team_section_cost.🤖 Generated with Claude Code