GH-48897: [C++] Benchmark and optimize CountSetBits#48898
Conversation
|
Also @AntoinePrv FYI |
|
@ursabot please benchmark |
|
Hmm, it seems performance is behind the expected theoretical throughput. From Agner Fog's instruction tables, I see that AMD Zen 2 should be able to sustain 4 POPCNT operations/cycle (reciprocal throughput = 0.25), i.e. 32 bytes/cycle on 64-bit ints. |
08383d7 to
9921e9d
Compare
|
Ok, the nested for-loop is un-nested by gcc 15.2.0... |
9921e9d to
d0f45cf
Compare
|
Updated benchmark numbers after I hand-unrolled the loop. |
|
@github-actions crossbow submit -g cpp |
|
Revision: d0f45cf Submitted crossbow builds: ursacomputing/crossbow @ actions-cdbe33a753 |
|
@ursabot please benchmark |
|
@rok I have deleted the branch, so I'm not sure that can work? |
|
I see the event on kubernetes, but the github api token was expired so it couldn't post back. |
|
Trying on #48907 |
|
After merging your PR, Conbench analyzed the 3 benchmarking runs that have been run so far on merge-commit ed35594. There were no benchmark performance regressions. 🎉 The full Conbench report has more details. It also includes information about 10 possible false positives for unstable benchmarks that are known to sometimes produce them. |
### Rationale for this change Counting the set bits in a null bitmap is an operation that comes often, it can be useful to get a more precise idea of its performance. ### What changes are included in this PR? 1. Add a benchmark for `CountSetBits`. 2. Hand-unroll its inner loop for better performance as otherwise the compiler may not respect the nested loop hint. Local results (AMD Zen 2): ``` ------------------------------------------------------------------------------ Benchmark Time CPU Iterations UserCounters... ------------------------------------------------------------------------------ CountSetBits/16 5.27 ns 5.27 ns 133267114 bytes_per_second=2.82991Gi/s CountSetBits/1024 35.1 ns 35.1 ns 19960309 bytes_per_second=27.178Gi/s CountSetBits/131072 3703 ns 3702 ns 184743 bytes_per_second=32.9698Gi/s ``` Local results (Intel(R) Core(TM) Ultra 7 255H): ``` ------------------------------------------------------------------------------ Benchmark Time CPU Iterations UserCounters... ------------------------------------------------------------------------------ CountSetBits/16 2.45 ns 2.45 ns 285392946 bytes_per_second=6.08012Gi/s CountSetBits/1024 28.9 ns 28.9 ns 23618777 bytes_per_second=33.0086Gi/s CountSetBits/131072 3490 ns 3489 ns 198472 bytes_per_second=34.9862Gi/s ``` ### Are these changes tested? By running said benchmark manually (and by Continuous Benchmarking). ### Are there any user-facing changes? No. * GitHub Issue: apache#48897 Authored-by: Antoine Pitrou <antoine@python.org> Signed-off-by: Antoine Pitrou <antoine@python.org>
Rationale for this change
Counting the set bits in a null bitmap is an operation that comes often, it can be useful to get a more precise idea of its performance.
What changes are included in this PR?
CountSetBits.Local results (AMD Zen 2):
Local results (Intel(R) Core(TM) Ultra 7 255H):
Are these changes tested?
By running said benchmark manually (and by Continuous Benchmarking).
Are there any user-facing changes?
No.