Skip to content

v5.3: 5x Faster Set Intersections with SVE2, NEON, and AVX-512

Choose a tag to compare

@ashvardanian ashvardanian released this 16 Sep 05:46
· 1941 commits to main since this release

set-intersections

  • Need to accelerate TF-IDF search ranking?
  • Joining large tables in an OLAP database?
  • Implementing graph algorithms?

Chances are - you need fast set intersections! It's one of the most common operations in programming, yet one of the hardest to accelerate with SIMD! This PR improves existing kernels and adds new ones for fast set intersections of sorted arrays of unique u16 and u32 values. Now, SimSIMD is not practically the only production codebase to use Arm SVE, but also one of the first to use the new SVE2 instructions available on Graviton 4 AWS CPUs, and coming to Nvidia's Grace Hopper, Microsoft Cobalt, and Google Axios! So upgrade to v5.2 and let's make the databases & search systems go 5x faster!

Speedups on x86

The new AVX-512 variant shows significant improvements in pairs/s across all benchmarks:

  • For |A|=128, |B|=128, |A∩B|=1, pairs/s increased
    • from 1.14M/s in the old implementation
    • to 7.73M/s in the new one, a 6.7x improvement.
  • At |A∩B|=64, the pairs/s rose:
    • from 1.13M/s in the old implementation
    • to 8.19M/s in the new one, a 7.2x gain.
  • For larger sets, like |A|=1024 and |B|=8192, with |A∩B|=10, pairs/s increased:
    • from 130.18k/s in the old implementation
    • to 194.50k/s in the new one, a 49% gain.

However, in cases like |A|=128, |B|=8192, with |A∩B|=64, pairs/s slightly decreased from 369.7k/s to 222.9k/s. Overall, the new implementation outperforms the previous one, and no case is worse than the serial version.

Speedups on Arm

On the Arm architecture, similar performance gains were achieved using the NEON and SVE2 instruction sets:

  • The optimized NEON implementation showed a 3.9x improvement in pairs/s for |A|=128, |B|=128, |A∩B|=1, going from 1.62M/s to 5.12M/s.
  • For |A∩B|=64 in the same configuration, performance improved from 1.60M/s to 5.51M/s, showing a 3.4x gain.
  • The SVE2 implementation also outperformed the previous SVE setup, achieving 5.6M/s (NEON) versus 1.27M/s (SVE) for |A|=128, |B|=128, |A∩B|=1, a 4.4x improvement.
  • In larger datasets, such as |A|=1024 and |B|=8192, the pairs/s increased from 49.3k/s to 110.03k/s, with NEON, and further to 109.47k/s with SVE2, nearly doubling the performance.

x86 Benchmarking Setup

The benchmarking was conducted on r7iz AWS instances with Intel Sapphire Rapids CPUs.

Running build_release/simsimd_bench
Run on (16 X 3900.51 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x8)
  L1 Instruction 32 KiB (x8)
  L2 Unified 2048 KiB (x8)
  L3 Unified 61440 KiB (x1)

Old Serial Baselines

-----------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                             Time             CPU   Iterations UserCounters...
-----------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1             567 ns          567 ns     24785678 pairs=1.76263M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1             567 ns          567 ns     24598141 pairs=1.76286M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1            569 ns          569 ns     24741572 pairs=1.75684M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1           568 ns          568 ns     24871638 pairs=1.76073M/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1           2508 ns         2508 ns      5591748 pairs=398.803k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1           2509 ns         2509 ns      5589871 pairs=398.535k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1          2530 ns         2530 ns      5564535 pairs=395.33k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1         2522 ns         2522 ns      5532306 pairs=396.447k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1           4791 ns         4791 ns      2920833 pairs=208.737k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1           4800 ns         4800 ns      2923139 pairs=208.346k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1          4821 ns         4820 ns      2906942 pairs=207.448k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1         4843 ns         4843 ns      2897334 pairs=206.504k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1         4484 ns         4484 ns      3122873 pairs=223.023k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1         4479 ns         4479 ns      3124662 pairs=223.261k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1        4484 ns         4484 ns      3125584 pairs=223.034k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1        4500 ns         4500 ns      3104588 pairs=222.229k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1        20118 ns        20117 ns       696244 pairs=49.7084k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1        20134 ns        20134 ns       696160 pairs=49.6682k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1       20125 ns        20124 ns       695799 pairs=49.6911k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1       20102 ns        20102 ns       695762 pairs=49.7464k/s

Existing AVX-512 Implementation

-------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                           Time             CPU   Iterations UserCounters...
-------------------------------------------------------------------------------------------------------------------------------
intersect_u16_ice<|A|=128d,|B|=128,|A∩B|=1>/min_time:10.000/threads:1             875 ns          875 ns     16248886 pairs=1.14342M/s
intersect_u16_ice<|A|=128d,|B|=128,|A∩B|=6>/min_time:10.000/threads:1             873 ns          873 ns     16081249 pairs=1.14555M/s
intersect_u16_ice<|A|=128d,|B|=128,|A∩B|=64>/min_time:10.000/threads:1            882 ns          882 ns     15851609 pairs=1.13354M/s
intersect_u16_ice<|A|=128d,|B|=128,|A∩B|=121>/min_time:10.000/threads:1           916 ns          916 ns     15282595 pairs=1091.32k/s
intersect_u16_ice<|A|=128d,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1            955 ns          955 ns     14660187 pairs=1047.53k/s
intersect_u16_ice<|A|=128d,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1            955 ns          955 ns     14663375 pairs=1047.57k/s
intersect_u16_ice<|A|=128d,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1           952 ns          952 ns     14702462 pairs=1050.17k/s
intersect_u16_ice<|A|=128d,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1          949 ns          949 ns     14743103 pairs=1053.59k/s
intersect_u16_ice<|A|=128d,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1           2718 ns         2718 ns      5168053 pairs=367.871k/s
intersect_u16_ice<|A|=128d,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1           2698 ns         2698 ns      5155819 pairs=370.664k/s
intersect_u16_ice<|A|=128d,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1          2705 ns         2705 ns      5203675 pairs=369.686k/s
intersect_u16_ice<|A|=128d,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1         2693 ns         2693 ns      5187007 pairs=371.377k/s
intersect_u16_ice<|A|=1024d,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1         7310 ns         7310 ns      1910292 pairs=136.8k/s
intersect_u16_ice<|A|=1024d,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1         7312 ns         7312 ns      1913190 pairs=136.759k/s
intersect_u16_ice<|A|=1024d,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1        7365 ns         7365 ns      1900946 pairs=135.781k/s
intersect_u16_ice<|A|=1024d,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1        7439 ns         7439 ns      1882319 pairs=134.43k/s
intersect_u16_ice<|A|=1024d,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1         7682 ns         7681 ns      1821784 pairs=130.183k/s
intersect_u16_ice<|A|=1024d,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1         7695 ns         7695 ns      1821861 pairs=129.955k/s
intersect_u16_ice<|A|=1024d,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1        7643 ns         7643 ns      1829955 pairs=130.842k/s
intersect_u16_ice<|A|=1024d,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1        7617 ns         7617 ns      1838612 pairs=131.279k/s

New AVX-512 Implementation

--------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                          Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_ice<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1             129 ns          129 ns    101989513 pairs=7.72559M/s
intersect_u16_ice<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1             134 ns          134 ns    107140278 pairs=7.46949M/s
intersect_u16_ice<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1            122 ns          122 ns    113134485 pairs=8.18634M/s
intersect_u16_ice<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1           114 ns          114 ns    122765163 pairs=8.75268M/s
intersect_u16_ice<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1           1042 ns         1042 ns     13412933 pairs=959.711k/s
intersect_u16_ice<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1           1035 ns         1035 ns     13423867 pairs=966.278k/s
intersect_u16_ice<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1          1038 ns         1038 ns     13401265 pairs=963.267k/s
intersect_u16_ice<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1         1055 ns         1055 ns     13170438 pairs=948.193k/s
intersect_u16_ice<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1           4315 ns         4315 ns      3024069 pairs=231.776k/s
intersect_u16_ice<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1           3999 ns         3999 ns      3371134 pairs=250.088k/s
intersect_u16_ice<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1          4486 ns         4486 ns      3278143 pairs=222.9k/s
intersect_u16_ice<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1         4525 ns         4525 ns      3170802 pairs=220.991k/s
intersect_u16_ice<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1          817 ns          817 ns     17102654 pairs=1.22419M/s
intersect_u16_ice<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1          820 ns          820 ns     17168886 pairs=1.22003M/s
intersect_u16_ice<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1         793 ns          793 ns     17756237 pairs=1.26107M/s
intersect_u16_ice<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1         747 ns          747 ns     18261381 pairs=1.33794M/s
intersect_u16_ice<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1         5142 ns         5142 ns      2728465 pairs=194.496k/s
intersect_u16_ice<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1         5114 ns         5114 ns      2727670 pairs=195.56k/s
intersect_u16_ice<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1        5142 ns         5142 ns      2716714 pairs=194.491k/s
intersect_u16_ice<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1        5151 ns         5151 ns      2721708 pairs=194.148k/s

Arm Benchmarking Setup

The benchmarking was conducted on r8g AWS instances with Graviton 4 CPUs.

Running build_release/simsimd_bench
Run on (2 X 2000 MHz CPU s)
CPU Caches:
  L1 Data 64 KiB (x2)
  L1 Instruction 64 KiB (x2)
  L2 Unified 2048 KiB (x2)
  L3 Unified 36864 KiB (x1)

Old Serial Baselines

----------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                            Time             CPU   Iterations UserCounters...
----------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1            615 ns          614 ns     22780083 pairs=1.62833M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1            610 ns          608 ns     22727971 pairs=1.64341M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1           622 ns          622 ns     22356453 pairs=1.60786M/s
intersect_u16_serial<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1          679 ns          679 ns     20641056 pairs=1.47332M/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1          2542 ns         2542 ns      5511491 pairs=393.332k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1          2539 ns         2539 ns      5512132 pairs=393.822k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1         2535 ns         2535 ns      5511950 pairs=394.436k/s
intersect_u16_serial<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1        2546 ns         2546 ns      5504586 pairs=392.843k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1          4122 ns         4122 ns      3374465 pairs=242.586k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1          4117 ns         4117 ns      3372418 pairs=242.884k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1         4138 ns         4138 ns      3374977 pairs=241.657k/s
intersect_u16_serial<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1        4142 ns         4142 ns      3361656 pairs=241.412k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1        4569 ns         4564 ns      3072148 pairs=219.129k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1        4557 ns         4557 ns      3075313 pairs=219.419k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1       4577 ns         4577 ns      3052064 pairs=218.472k/s
intersect_u16_serial<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1       4728 ns         4728 ns      2980530 pairs=211.504k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1       20278 ns        20273 ns       690191 pairs=49.3276k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1       21192 ns        20272 ns       691680 pairs=49.3302k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1      21438 ns        20268 ns       689617 pairs=49.3384k/s
intersect_u16_serial<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1      22010 ns        20317 ns       692675 pairs=49.2207k/s

Old SVE Implementation

-------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                         Time             CPU   Iterations UserCounters...
-------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_sve<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1            794 ns          788 ns     17715501 pairs=1.26918M/s
intersect_u16_sve<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1            809 ns          785 ns     17579527 pairs=1.27438M/s
intersect_u16_sve<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1           819 ns          810 ns     17229391 pairs=1.23482M/s
intersect_u16_sve<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1          878 ns          856 ns     16347952 pairs=1.16827M/s
intersect_u16_sve<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1          1475 ns         1380 ns     10129190 pairs=724.869k/s
intersect_u16_sve<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1          1400 ns         1361 ns     10312201 pairs=734.514k/s
intersect_u16_sve<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1         1353 ns         1344 ns     10427410 pairs=743.793k/s
intersect_u16_sve<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1        1369 ns         1350 ns     10516190 pairs=740.815k/s
intersect_u16_sve<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1          7156 ns         7009 ns      1991602 pairs=142.677k/s
intersect_u16_sve<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1          7095 ns         6982 ns      2006057 pairs=143.232k/s
intersect_u16_sve<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1         7328 ns         6967 ns      2004803 pairs=143.537k/s
intersect_u16_sve<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1        6966 ns         6963 ns      2013422 pairs=143.624k/s
intersect_u16_sve<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1        7119 ns         6517 ns      2143784 pairs=153.437k/s
intersect_u16_sve<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1        6978 ns         6522 ns      2146331 pairs=153.331k/s
intersect_u16_sve<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1       6721 ns         6533 ns      2141325 pairs=153.067k/s
intersect_u16_sve<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1       7046 ns         6675 ns      2095016 pairs=149.823k/s
intersect_u16_sve<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1       10819 ns        10722 ns      1307796 pairs=93.2695k/s
intersect_u16_sve<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1       11295 ns        10729 ns      1305575 pairs=93.2031k/s
intersect_u16_sve<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1      10596 ns        10596 ns      1317798 pairs=94.3769k/s
intersect_u16_sve<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1      10527 ns        10486 ns      1337148 pairs=95.3626k/s

New NEON Implementation

--------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                          Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_neon<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1            195 ns          195 ns     72473251 pairs=5.12346M/s
intersect_u16_neon<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1            193 ns          193 ns     71826322 pairs=5.17983M/s
intersect_u16_neon<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1           181 ns          181 ns     76859132 pairs=5.51211M/s
intersect_u16_neon<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1          161 ns          161 ns     86301671 pairs=6.22906M/s
intersect_u16_neon<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1          1199 ns         1027 ns     13866808 pairs=973.295k/s
intersect_u16_neon<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1          1171 ns         1034 ns     13729254 pairs=966.886k/s
intersect_u16_neon<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1         1120 ns         1038 ns     13671085 pairs=963.804k/s
intersect_u16_neon<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1        1150 ns         1051 ns     13070692 pairs=951.238k/s
intersect_u16_neon<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1          2587 ns         2446 ns      5685615 pairs=408.885k/s
intersect_u16_neon<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1          2595 ns         2490 ns      5538880 pairs=401.615k/s
intersect_u16_neon<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1         2482 ns         2460 ns      5704185 pairs=406.459k/s
intersect_u16_neon<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1        2512 ns         2512 ns      5592948 pairs=398.064k/s
intersect_u16_neon<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1        1599 ns         1573 ns      8893290 pairs=635.781k/s
intersect_u16_neon<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1        1570 ns         1570 ns      8950291 pairs=637.098k/s
intersect_u16_neon<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1       1488 ns         1488 ns      9449103 pairs=672.121k/s
intersect_u16_neon<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1       1332 ns         1332 ns     10582682 pairs=751.007k/s
intersect_u16_neon<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1        8997 ns         8997 ns      1556944 pairs=111.144k/s
intersect_u16_neon<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1        8999 ns         8999 ns      1554324 pairs=111.128k/s
intersect_u16_neon<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1       9126 ns         9070 ns      1543769 pairs=110.257k/s
intersect_u16_neon<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1       9089 ns         9089 ns      1536462 pairs=110.029k/s

New SVE2 Implementation

--------------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                          Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------------------------------------------------
intersect_u16_sve2<|A|=128,|B|=128,|A∩B|=1>/min_time:10.000/threads:1            179 ns          178 ns     77997900 pairs=5.60245M/s
intersect_u16_sve2<|A|=128,|B|=128,|A∩B|=6>/min_time:10.000/threads:1            179 ns          179 ns     77959137 pairs=5.59776M/s
intersect_u16_sve2<|A|=128,|B|=128,|A∩B|=64>/min_time:10.000/threads:1           170 ns          170 ns     82829421 pairs=5.88598M/s
intersect_u16_sve2<|A|=128,|B|=128,|A∩B|=121>/min_time:10.000/threads:1          143 ns          143 ns     97771708 pairs=6.9995M/s
intersect_u16_sve2<|A|=128,|B|=1024,|A∩B|=1>/min_time:10.000/threads:1           900 ns          900 ns     15430306 pairs=1.11111M/s
intersect_u16_sve2<|A|=128,|B|=1024,|A∩B|=6>/min_time:10.000/threads:1           909 ns          909 ns     15374525 pairs=1099.58k/s
intersect_u16_sve2<|A|=128,|B|=1024,|A∩B|=64>/min_time:10.000/threads:1          922 ns          922 ns     15025863 pairs=1085.12k/s
intersect_u16_sve2<|A|=128,|B|=1024,|A∩B|=121>/min_time:10.000/threads:1         932 ns          932 ns     15083373 pairs=1072.6k/s
intersect_u16_sve2<|A|=128,|B|=8192,|A∩B|=1>/min_time:10.000/threads:1          2135 ns         2135 ns      6460842 pairs=468.333k/s
intersect_u16_sve2<|A|=128,|B|=8192,|A∩B|=6>/min_time:10.000/threads:1          2118 ns         2118 ns      6509484 pairs=472.238k/s
intersect_u16_sve2<|A|=128,|B|=8192,|A∩B|=64>/min_time:10.000/threads:1         2138 ns         2138 ns      6468742 pairs=467.706k/s
intersect_u16_sve2<|A|=128,|B|=8192,|A∩B|=121>/min_time:10.000/threads:1        2136 ns         2136 ns      6419653 pairs=468.097k/s
intersect_u16_sve2<|A|=1024,|B|=1024,|A∩B|=10>/min_time:10.000/threads:1        1502 ns         1502 ns      9329372 pairs=665.698k/s
intersect_u16_sve2<|A|=1024,|B|=1024,|A∩B|=51>/min_time:10.000/threads:1        1492 ns         1492 ns      9375601 pairs=670.246k/s
intersect_u16_sve2<|A|=1024,|B|=1024,|A∩B|=512>/min_time:10.000/threads:1       1416 ns         1416 ns      9859829 pairs=706.16k/s
intersect_u16_sve2<|A|=1024,|B|=1024,|A∩B|=972>/min_time:10.000/threads:1       1274 ns         1274 ns     11052636 pairs=785.05k/s
intersect_u16_sve2<|A|=1024,|B|=8192,|A∩B|=10>/min_time:10.000/threads:1        9148 ns         9148 ns      1528714 pairs=109.319k/s
intersect_u16_sve2<|A|=1024,|B|=8192,|A∩B|=51>/min_time:10.000/threads:1        9150 ns         9150 ns      1529679 pairs=109.287k/s
intersect_u16_sve2<|A|=1024,|B|=8192,|A∩B|=512>/min_time:10.000/threads:1       9148 ns         9147 ns      1527762 pairs=109.32k/s
intersect_u16_sve2<|A|=1024,|B|=8192,|A∩B|=972>/min_time:10.000/threads:1       9135 ns         9135 ns      1529316 pairs=109.473k/s