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

   The benchmark bot reran the `divisor` benchmark on 
63ae1539bf03bbea3302c06094984320ba89160b, which has the same benchmark code as 
the PR head, on 
[x86](https://github.com/apache/arrow-rs/pull/11467#issuecomment-6085819805) 
and 
[arm64](https://github.com/apache/arrow-rs/pull/11467#issuecomment-6085908520). 
Each run compares the commit to itself, so the charts show `operator` time 
divided by `divisor` time from the changed column.
   
   <img width="1600" height="1380" alt="divisor-types-enum-bot-x86" 
src="https://github.com/user-attachments/assets/568f551b-2a98-49e3-89af-345e97832fa4";
 />
   
   <img width="1600" height="1380" alt="divisor-types-enum-bot-arm" 
src="https://github.com/user-attachments/assets/ecc4dff1-1c8b-4c3a-91ee-7fc2684da756";
 />
   
   `wrapping_div_rem` is faster than `/` and `%` in all 32 cases on both 
runners. The smallest gain is 1.8x, for `i64 % 13` on x86.
   
   @andygrove, in your review you asked to
   
   > check that the inner loop is vectorized in the bot's thin-LTO build before 
using its numbers.
   
   I built the `divisor` benchmark with the bot's setting 
(`CARGO_PROFILE_BENCH_LTO=thin`) for aarch64 and for x86-64 without a 
`target-cpu`, and read the disassembly of the benchmark binary. Each benchmark 
matches on the variant once per batch, outside the loop. None of the inner 
loops branches on the divisor or reloads its fields. On aarch64, the 32-bit 
loops and the 64-bit `PowerOfTwo` loops are NEON loops. The 64-bit `Multiplier` 
division loops compute `umulh` or `smulh` in scalar registers for two values 
per iteration and do the rest in NEON registers, and the 64-bit `Multiplier` 
remainder loops are scalar. On x86-64, every case has an SSE2 main loop, and 
the 64-bit `Multiplier` loops compute the high multiplies with scalar `mul` for 
two values per iteration.
   
   On Neoverse-V2, `u32 % 16` now takes 0.41 us, the same as `u32 / 16`. In the 
[earlier 
run](https://github.com/apache/arrow-rs/pull/11467#issuecomment-6070944047) it 
took 5.5 us. `/` and `%` by 16 take 13.7 to 16.5 us there, against 30.0 to 56.2 
us by 13, so three of the divide-by-16 bars are shorter than the divide-by-13 
bars.
   
   <details><summary>Numbers behind the charts (us per 8192 values)</summary>
   
   | Case | x86 `operator` | x86 `divisor` | x86 speedup | arm64 `operator` | 
arm64 `divisor` | arm64 speedup |
   |---|---|---|---|---|---|---|
   | `u32 / 13` | 15.1 | 2.2 | 6.9x | 31.5 | 1.69 | 18.7x |
   | `u32 % 13` | 15.1 | 4.0 | 3.8x | 32.2 | 1.77 | 18.2x |
   | `i32 / 13` | 15.1 | 5.8 | 2.6x | 30.0 | 2.1 | 14.3x |
   | `i32 % 13` | 15.1 | 7.7 | 2.0x | 30.7 | 2.4 | 12.8x |
   | `u64 / 13` | 25.1 | 6.2 | 4.0x | 53.4 | 5.2 | 10.3x |
   | `u64 % 13` | 24.8 | 9.6 | 2.6x | 56.2 | 5.2 | 10.8x |
   | `i64 / 13` | 24.7 | 9.6 | 2.6x | 52.0 | 6.0 | 8.7x |
   | `i64 % 13` | 24.7 | 13.6 | 1.8x | 54.7 | 6.5 | 8.4x |
   | `u32 / 16` | 15.1 | 0.87 | 17.3x | 13.7 | 0.41 | 33.3x |
   | `u32 % 16` | 15.1 | 0.74 | 20.3x | 14.4 | 0.41 | 35.3x |
   | `i32 / 16` | 15.1 | 1.49 | 10.2x | 13.7 | 1.32 | 10.4x |
   | `i32 % 16` | 15.1 | 1.13 | 13.4x | 14.4 | 1.10 | 13.1x |
   | `u64 / 16` | 24.6 | 1.51 | 16.3x | 13.7 | 0.80 | 17.2x |
   | `u64 % 16` | 24.8 | 1.45 | 17.1x | 16.5 | 0.80 | 20.7x |
   | `i64 / 16` | 24.7 | 4.2 | 5.9x | 13.7 | 2.6 | 5.3x |
   | `i64 % 16` | 25.0 | 2.6 | 9.6x | 16.5 | 2.2 | 7.5x |
   
   </details>


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