mbutrovich opened a new issue, #12169: URL: https://github.com/apache/arrow-rs/issues/12169
### Is your feature request related to a problem or challenge? Part of #11421. [`make_downscaler`](https://github.com/apache/arrow-rs/blob/6b34163d51aa59f7cac2edcb74e8bd1ddc6b9120/arrow-cast/src/cast/decimal.rs#L235-L246) divides every value by 10^(scale difference) and rounds half away from zero. The divisor is known once per cast. For `Decimal128` that is a `__divti3` call per value. The cast already divides once per row (#11454, #11528). ### Describe the solution you'd like Build a divisor per batch and use it in the closure of `make_downscaler`, for `Decimal32`, `Decimal64`, `Decimal128` and `Decimal256`. This needs the divisors from {{01}} for the 128-bit and 256-bit types and the half-up helper from {{02}}. The 32-bit and 64-bit types can start with #11467 alone. For `Decimal128` and `Decimal256`, pick the variant per batch from the magnitude of the values (see {{01}}). On the 18-digit and 15-digit cases below, the 128-bit variant alone is slower than today, and the 64-bit one is 1.9x faster. The PR needs `Decimal128` and `Decimal256` benchmark cases with narrow and wide values from `decimal_downscale` (#11426), reports the bot's before and after numbers, and keeps the results of the fallible cast with `safe: false` and `safe: true` unchanged. ### Describe alternatives you've considered `strength_reduce` is the third column below. It was slower than the fastest variant in every row except the fallible cast. ### Additional context The arrow-cast `decimal_downscale` benchmark calls `cast` on an 8192-value array, with each method in `make_downscaler`, on an Apple M5 Max in us per batch (medians of three runs). Today is `main` at `6b34163`. <img width="1600" height="1236" alt="Image" src="https://github.com/user-attachments/assets/dddacee5-1d11-470d-83f7-d3678fe2d98b" /> | Cast | Today | `strength_reduce` | Granlund-Montgomery | Granlund-Montgomery with the per-batch 64-bit path | |---|---|---|---|---| | `(18, 6)` to `(18, 2)`, 18-digit values | 21.3 | 19.5 (1.1x) | 24.8 (0.9x) | **11.5 (1.9x)** | | `(38, 10)` to `(38, 2)`, 15-digit values | 21.4 | 19.5 (1.1x) | 24.7 (0.9x) | **11.4 (1.9x)** | | `(38, 10)` to `(38, 2)`, 38-digit values | 32.4 | 28.8 (1.1x) | **24.7 (1.3x)** | 26.8 (1.2x) | | `(38, 20)` to `(38, 2)`, 38-digit values | 73.7 | 28.7 (2.6x) | **24.7 (3.0x)** | 26.8 (2.8x) | | `(38, 10)` to `(30, 2)`, 30-digit values, fallible | 42.4 | **34.4 (1.2x)** | 36.4 (1.2x) | 38.2 (1.1x) | The per-batch 64-bit path in this table used the hardware divide. A separate run with Granlund-Montgomery's 64-bit variant there measured within 2% of it (11.2 vs 11.4 us for 18-digit values). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
