mbutrovich commented on PR #11467:
URL: https://github.com/apache/arrow-rs/pull/11467#issuecomment-6426381403

   Thanks @mightsleep and @devanbenz. I adopted the `u32` split, the signed 
remainder, and the correctness checks at the ends of the last quotient steps. 
The enums are now `#[non_exhaustive]`, so a later variant isn't a breaking 
change.
   
   The benchmark bot compared the new forms with the PR's previous ones in the 
same run, on 
[x86_64](https://github.com/apache/arrow-rs/pull/11467#issuecomment-6426118997) 
(Xeon Platinum 8581C, `x86-64-v3`) and 
[arm64](https://github.com/apache/arrow-rs/pull/11467#issuecomment-6426111643) 
(Neoverse-V2). The ratios are previous time over new time.
   
   <img width="1600" height="932" alt="divisor-variants-bot-x86" 
src="https://github.com/user-attachments/assets/5a539a7a-d4ca-42a4-a9b5-d76984d853ed";
 />
   
   <img width="1600" height="932" alt="divisor-variants-bot-arm" 
src="https://github.com/user-attachments/assets/47120a34-e3fa-46db-93c8-78032c676636";
 />
   
   
   | Case | Variant | x86_64 `/` | x86_64 `%` | arm64 `/` | arm64 `%` |
   |---|---|---|---|---|---|
   | `u32` by 13 | `Up` | 1.24x | 1.27x | 1.60x | 1.27x |
   | `u32` by 7 | `Down` | 0.97x | 1.13x | 1.27x | 1.21x |
   | `u64` by 13 | `Up` | 0.94x | 1.13x | 1.58x | 1.17x |
   | `i32` by 13 | `AddIndicator` | 1.00x | 1.16x | 1.00x | 1.34x |
   | `i64` by 13 | `AddIndicator` | 1.00x | 1.05x | 1.00x | 1.15x |
   
   On an Apple M5 Max the same comparison gave 1.47x and 1.38x for `u32` with 
`Up`, 1.19x and 1.17x for `u32` with `Down`, 1.78x and 1.41x for `u64` with 
`Up`, and 1.28x and 1.57x for the `i32` and `i64` remainders.
   
   Two cases lose a little on the Xeon. `u64 /` with `Up` is 0.94x. In the 
thin-LTO build for `x86-64-v3`, that loop computes each high multiply with a 
scalar `mulx` and moves it into a vector register, and `Up` removes only vector 
instructions from it. `u32 /` with `Down` is 0.97x. Both gain 1.13x on `%`, and 
both gain on the two Arm CPUs, so I kept them.
   
   A few things I tried and left out:
   
   - `Down` for `u64` was 0.71-0.73x on the Xeon and 0.95-0.97x for `%` on the 
M5, though it gained 1.10-1.13x on Neoverse-V2.
   - Computing `Down` as `m * n + m` in the double-width product instead of a 
saturating increment was 0.42-0.78x on every CPU. LLVM rewrites it as `m * (n + 
1)` in 64-bit lanes, which needs a full 64-bit multiply.
   - The direct remainder from figures 1 and 2 of Lemire, Kaser and Kurz was 
0.67-0.71x on the M5. It needs a 64-bit low multiply and a 64x64 high multiply 
per value, so it vectorizes worse than the quotient-based remainder in 32-bit 
lanes.
   


-- 
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]

Reply via email to