Repository navigation
feat(basic): zip_reduce, the widening two-input reduction; documented evaluation order (#280) - #319
Merged
Merged
Conversation
`dot` pins its result type to `A: Mul<B, Output = R>`, so f32 operands cannot be accumulated in f64. #280's remaining substance is exactly that gap: the raw allocation-free entries it also asked for were superseded by 0.6.0's inline metadata and planning at rank <= INLINE_RANK. `zip_reduce(a, b, map, combine, init)` is the two-operand sibling of `reduce`: the accumulator type comes from the map closure (`Fn(A, B) -> U`), each operand's ElementOp is applied before the map, and it reuses the existing fused planner plus the full-reduction threading tree (no second traversal engine). Permuted, gapped, negative and stride-0 operands work, and the rank <= INLINE_RANK call is allocation-free, serial and threaded. Docs on `reduce`, `sum`, `dot` and `zip_reduce` now state the evaluation order: independent of the ambient pool width under the sequential policy (ExecContext::serial / ExecutionPolicy::Sequential), repeatable for a fixed thread count under a parallel policy, never a strict left-to-right fold, and never a cross-machine bitwise guarantee. Each also states the allocation bound. Tests: `zip_reduce.rs` (f32->f64 widening, six layouts against a naive reference, ElementOp honouring, empty operand, shape/rank rejection, the parallel branch above the threshold, serial-policy bitwise identity inside 1/2/4-worker pools, parallel repeatability, and a positive control that the determinism data observably depends on fold order) and new alloc-matrix rows for `sum`, `reduce` and `zip_reduce` at rank 1..=8 with contiguous, permuted and stride-0 operands, both sides of the small-tensor threshold and above the threading threshold.
`erased-execution-policy.md` gains a "Reduction evaluation order and the deterministic route" section: the sequential policy is the pool-width independent route and is asserted for reduce/zip_reduce/sum/dot, a parallel policy is repeatable only for a fixed thread count, and `zip_reduce` joins the covered full-reduction family. The worklog records what #280 asked for, why the raw entries stay superseded, what landed, the gate results, and that no version is bumped (the strided-basic 0.6.1 release is a separate PR).
…ning Post-review of the zip_reduce change. A zero-extent dimension makes any stride representable, so a valid empty view such as dims [0, 2] with strides [0, isize::MAX] passed shape validation and then reached the block planner, where isize::MAX * 8 overflowed (with overflow checks on). `zip_reduce`, `reduce` and `sum` all panicked on that input; `dot` happened to survive only because its small tensor plan builder did not multiply. All four entries now return their identity for zero elements right after shape validation and checked element counting, and `zip_reduce` reuses that count instead of recomputing it. `reduce_axis` already returned the identity for an empty reduced axis. Also from the same review: - the parallel contiguous leaf now wraps `fold_contiguous2` in `simd::dispatch_if_large`, exactly as `reduce` dispatches each of its parallel contiguous leaves, so the two routes take the same runtime target-feature dispatch; - the forwarding-only `zip_reduce_impl` boundary is gone; its body lives in `zip_reduce`; - lib.rs and docs/design/erased-execution-policy.md now distinguish `dot` (no parallel branch under any policy) from the reductions that fan out, instead of implying the sequential policy is the only reproducible route for every entry. Tests: the empty-layout reproducer for all four entries; the above-threshold contiguous layout (which reaches the contiguous parallel leaf) is now part of the naive-reference, serial-identity and repeatability checks, not only of the allocation matrix, and the test module docs say so. Deliberately not shared: `fold_contiguous2` still mirrors `fold_contiguous`'s lane scheduling by hand. Routing `fold_contiguous` through a generic index-accessor lane helper measured 0.34 ns/element against 0.11 ns/element on a contiguous f64 `reduce` of 1 MiB (release, -j 4); the chunks_exact + zip form is what keeps the 16 lanes bound-check free. The measurement is recorded on the function and in the worklog.
Repository rules reviewRepository rules review (55c7bb4cc6d42c3d0db0fbbce822aa3b260005f1...a83192b4ae0c982672df50ed1375305d04499f4c) Verdict: pass Findings: - [warn] llm-skipped (External LLM Review) <unknown>: External LLM review was skipped External LLM review is permanently disabled; deterministic checks only. |
This was referenced Oct 18, 2026
shinaoka
added a commit
that referenced
this pull request
Oct 18, 2026
Additive: zip_reduce (the widening two-input reduction), the documented evaluation order, and the empty-view identity return (#319). Release note: docs/worklogs/2026-10-18-issue-280-widening-reduce.md. Other crates stay at 0.6.0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shinaoka
added a commit
that referenced
this pull request
Oct 18, 2026
Additive: zip_reduce (the widening two-input reduction), the documented evaluation order, and the empty-view identity return (#319). Release note: docs/worklogs/2026-10-18-issue-280-widening-reduce.md. Other crates stay at 0.6.0. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Closes #280.
Summary
strided_basic::zip_reduce(a, b, map, combine, init): the two-operand sibling ofreduce. Each operand'sElementOp(e.g.Conj) is applied beforemap, so a widening dot (f32 inputs summed in f64) needs no copy. It reuses the existing planner and traversal (build_plan_fused, the threaded fold helpers). There is no second traversal engine.reduce,zip_reduce,sumanddot, and indocs/design/erased-execution-policy.md:ExecContext::serial()/ExecutionPolicy::Sequentialthe result does not depend on the ambient pool width.dothas no parallel branch under any policy.INLINE_RANK.reduce,zip_reduce,sumanddot. They now return the identity right after shape validation.StridedView::newand kernel planning are inline at rank ≤ 8, sodot/sum/reduceover borrowed views do not allocate. Conjugation is anElementOp.Verification (local, 4 cores)
cargo test --workspace(default and--all-features): pass.tests/zip_reduce.rs(10 tests): widening, six layouts against a naive reference,Conj, empty views, and the parallel contiguous and gapped branches against an exact reference. The serial result is bitwise identical under 1/2/4-worker pools, and parallel runs are repeatable. A positive control shows the fold order is observable.tests/alloc_matrix.rs: 0 allocations forzip_reduce,reduceandsumat rank 1..=8 (contiguous, permuted, stride-0, serial and two-worker).OVERHEAD_GATE=1 overhead_smoke: S3a 1.69 ≤ 2.5, S3b 2.63 ≤ 4.reducegot 3x slower, becausechunks_exact+zipkeeps the 16 lanes vectorized. This is documented onfold_contiguous2.Additive; release as strided-basic 0.6.1 in a follow-up release PR.
🤖 Generated with Claude Code