simd: masked_strided_group_sum — the strided sub-word gather consumers lacked - #283
Merged
Merged
Conversation
…s lacked Closes a named gap rather than adding surface speculatively. lance-graph-java's mask-native sweep needed "gather a sub-word group out of a strided register under a runtime grouping and widen-accumulate": masked_sum_i32 is contiguous i32, eq_u32_strided_to_mask reads one aligned u32 per record, and neither covers it. The consumer carried its own scalar loop and documented the absence as a W1a gap -- added THERE, consumed here -- which is exactly the shape the "all SIMD from ndarray::simd" invariant asks for. The kernel is scalar, and the doc says why with the reasoning rather than an apology: one small register per record at a large stride (512 bytes in the motivating case) is memory-bound, records are not adjacent so several cannot be vector-loaded, and widening six u16s inside one record would optimise the part that is already free. A contiguous or small-stride variant WOULD vectorise and is named as a different primitive, not a flag on this one. Overflow accumulates in i128 and range-checks once, returning None rather than a wrapped value: with group_bytes = 4 a single record contributes up to groups × (2^32 - 1). Sub-word loads are byte-wise because a group's offset is not guaranteed aligned for a 3-byte grouping, and an unaligned wide read is UB in Rust even where the hardware tolerates it. Six tests, each falsifiable: the three groupings of one register must give three DIFFERENT answers (so a kernel ignoring its grouping fails); the mask and stride both bind; a dirty tail bit past n_records is ignored; overflow is reported with the row bound asserted rather than narrated; and the two contract violations (group_bytes outside 1..=4, a record reading past the buffer) panic.
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b253c248-01f9-482d-8bd0-90ec71b1e3ef) |
AdaWorldAPI
marked this pull request as ready for review
August 25, 2026 12:29
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 a named gap rather than adding surface speculatively.
lance-graph-java's mask-native sweep needed "gather a sub-word group out of a strided register under a runtime grouping and widen-accumulate".masked_sum_i32is contiguousi32;eq_u32_strided_to_maskreads one alignedu32per record. Neither covers it, so the consumer carried its own scalar loop and documented the absence as a W1a gap — added THERE, consumed here — which is the shape the "all SIMD fromndarray::simd" invariant asks for. That consumer's loop is now one delegating call.The kernel is scalar, and the doc gives the reasoning rather than an apology
One small register per record at a large stride (512 bytes in the motivating case) is memory-bound; records are not adjacent so several cannot be vector-loaded; and widening six
u16s inside one record would optimise the part that is already free. A contiguous or small-stride variant would genuinely vectorise and is named as a different primitive — not a flag on this one.Correctness details that are easy to get wrong
i128, range-checks once. Withgroup_bytes = 4one record contributes up togroups × (2³² − 1).masked_sum_i32.Tests
Six, each falsifiable — notably that the three groupings of one register must give three different answers, so a kernel ignoring its grouping fails; plus the two contract violations (
group_bytesoutside1..=4, a record reading past the buffer) asshould_panic.Generated by Claude Code