Repository navigation
Add shared conversion to canonical decimal arrays or Widen - #11005
Conversation
Merging this PR will improve performance by 21.13%1 warning
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
eb6bfc5 to
b3b006c
Compare
b3b006c to
e50341e
Compare
e50341e to
d030931
Compare
d030931 to
0c45ef9
Compare
73a9038 to
bf6bc81
Compare
bf6bc81 to
0892933
Compare
0892933 to
a1837f2
Compare
7aa8c56 to
9997931
Compare
5f17d7b to
9f36e20
Compare
9f36e20 to
754e893
Compare
Widen
Widen7102a1e to
a19248e
Compare
There was a problem hiding this comment.
this is effectively the old vortex-array/src/arrays/widen/encode.rs
d2db6b0 to
fe14932
Compare
Tracking Issue: #10701 Stacked on #11003. #11005 builds on it. No release gate. ## Summary Decimal widening preserves order, equality and validity, so ordered aggregates can use the child instead of copying it first. Sum also needs the logical result precision: using the child's sum dtype could overflow a result that should fit. ## Changes Ordered aggregates widen their child partials, and MinMax reuses exact cached child extrema before scanning. Decimal `Sum` runs in the logical sum dtype only when the legacy `Stat::Sum` path combines independent batch totals. `SumV2` and `Sum` without `skip_nans` keep the fallback because their running sum can cancel a batch total that would overflow on its own. Tests compare running partials against fresh canonical batches so cached statistics cannot hide kernel work. <details> <summary>Historical local benchmark results</summary> These retained measurements predate this style pass and rebase. They do not measure the current head. `cargo bench -p vortex-array --bench widen_decimal`, Apple M4, medians. The numbers were measured at the top of this stack before the split, so they cover the whole stack, not this layer alone. The baseline is the canonical input, and the candidate is the same values as a `Widen` (child precision 5 under precision 10, 9 under 18, and 18 under 38). CodSpeed on this PR measures the layer itself. | bench | p10 canonical | p10 Widen | p18 canonical | p18 Widen | p38 canonical | p38 Widen | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | `min_max` | 14.93 µs | 15.12 µs | 14.62 µs | 15.12 µs | 21.58 µs | 14.95 µs | `sum` medians are within 8% of the canonical input at every precision. </details> ## API Changes None. Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Storage width alone cannot determine a valid decimal child precision. For example, unscaled 127 fits i8 but requires precision 3 and an i16 canonical child. Share child selection between encoding and stored-value reads so comparisons and aggregates can trust the selected child dtype. Reuse canonical buffers without scanning, including device buffers. Resolve other widths on the host from valid-value bounds and scale, retaining the range exactness in child statistics. Validate buffer layout and validity length before typed access, and use checked constructors. Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Remove the local signed/unsigned conversion helper. Its callers already establish non-null integer values, and PValue::as_i128 holds every integer PValue exactly. The scalar type-selection helper is now infallible. Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Explain why legacy decimal nodes and DecimalByteParts output need canonical conversion, including why only noncanonical widths require host access. Keep range resolution and statistic exactness together, share canonical array construction, and use vortex_ensure_eq for validity length. Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
fe14932 to
fe24fc7
Compare
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
|
I think you can reduce some of the redundant test coverage here |
Tracking Issue: #10701 Top of the decimal `Widen` stack, on #11005. No release gate. ## Summary A same-scale precision increase copied every value into a wider buffer even when the caller did not need the values yet. Returning a `Widen` defers that copy and lets subsequent kernels keep working on the narrow child. Basically, we might as well keep things in `Widen` form instead of casting immediately. ## Changes The child retains the source dtype and statistics because its values are unchanged. A cast of a decimal `Widen` passes to that child. Execution copies into the logical width directly, since yielding another widening cast would return a `Widen` again. The default-writer test compares round-trip values. Known cost: the retained benchmarks show slower filtering at precision 38 (see #10946). <details> <summary>Historical local benchmark results</summary> These retained measurements predate this style pass and rebase. They do not measure the current head. `cargo bench -p vortex-array --bench widen_decimal`, Apple M4, medians. The numbers were measured at the top of this stack before the split, so they cover the whole stack, not this layer alone. The baseline is the canonical input, and the candidate is the same values as a `Widen` (child precision 5 under precision 10, 9 under 18, and 18 under 38). CodSpeed on this PR measures the layer itself. | bench | p10 canonical | p10 Widen | p18 canonical | p18 Widen | p38 canonical | p38 Widen | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | `cast_widen` | 12.08 µs | 6.958 µs | 12.33 µs | 6.958 µs | 16.54 µs | 14.58 µs | </details> ## API Changes A same-scale decimal cast returns a `Widen` when the target precision grows the canonical width. --------- Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Tracking Issue: #10701
Stacked on #11004.
Summary
Legacy decimal nodes and DecimalByteParts decoding can produce a
DecimalArraywhose stored width differs from the canonical width of its dtype. Those arrays cannot pass through unchanged onceDecimalArrayrequires canonical storage. Rejecting them would break existing data, while widening every buffer would discard the narrow storage thatWidenis meant to preserve.The migration therefore needs a shared conversion from these stored buffers into either a canonical decimal array or a
Widenover a canonical decimal child. This PR provides that conversion for the reader and decoder follow-ups, preserving the logical dtype and retaining narrow buffers where possible. Sharing child selection with decimal encoding keeps the resulting child dtypes consistent.Changes
Shares child selection between decimal encoding and stored-value conversion. Already-canonical buffers are reused without scanning, including device buffers. Other widths are handled on the host, selecting a valid child dtype or copying to the logical canonical width when no narrower child fits.
The reader integration is in #10995, which uses this helper when deserializing
vortex.decimalnodes. #10905 uses it for DecimalByteParts decoding. This PR provides the common conversion without changing either read path yet.Tests cover conversion, buffer reuse, range statistics, and malformed inputs. Formatting, DCO, and clippy hooks passed. Tests were not run.
API Changes
Adds
WidenArray::from_stored_decimal(parts, known_range, ctx)for converting stored decimal buffers. A supplied range must contain every valid unscaled value, and an exact range must give the actual extrema.