On Thu, 2 Jul 2026 12:42:00 GMT, Ehsan Behrangi <[email protected]> wrote:

>> But what's the point of exposing more independent work to the scheduler, 
>> when that work doesn't do anything useful?
>> 
>> Do you have the version without the reduction each time so we can compare it 
>> on other implementations?
>
> Yes. I implemented that version for comparison.
> 
> I have two standalone AArch64/NEON P16 implementations:
> 
> reduce_loop: performs the horizontal reduction inside every 16-byte iteration.
> reduce_end: keeps 16 logical accumulators (four NEON vectors) across the loop 
> and performs a single reduction after processing all blocks (AArch64 current 
> stub is a smarter(less vector registers) implementation of this algorithm 
> too).
> 
> For this experiment, both implementations assume:
> 
> input length is a multiple of 16,
> no tail handling,
> seed = 0.
> 
> On my test system, both implementations produce the same result as the scalar 
> reference for the tested lengths under those assumptions.
> 
> At 64 KB, I measured:
> 
> reduce_loop: 0.0976 ns/byte
> reduce_end : 0.1316 ns/byte
> 
> reduce_loop was consistently faster across all tested lengths from 16 bytes 
> up to 64 KB.
> 
> I've also included a small benchmark driver and build/run instructions so 
> others can reproduce the comparison:
> [hash.zip](https://github.com/user-attachments/files/29598153/hash.zip)
> 
> g++ -O3 -march=armv8-a -o hash_bench \
>     driver.cpp \
>     hash_jdk_neon_reduce_loop.S \
>     hash_jdk_neon_reduce_end.S
> ./hash_bench
> 
> This is detailed output:
> === Correctness display only; mismatch is OK for this experiment ===
> len=   16  scalar=0xCAD5BD38  loop=0xCAD5BD38  end=0xCAD5BD38
> len=   32  scalar=0x20787A70  loop=0x20787A70  end=0x20787A70
> len=   64  scalar=0xB196B3E0  loop=0xB196B3E0  end=0xB196B3E0
> len=  128  scalar=0x5E42E8C0  loop=0x5E42E8C0  end=0x5E42E8C0
> len=  256  scalar=0xF24DEF80  loop=0xF24DEF80  end=0xF24DEF80
> len=  512  scalar=0x07ABDF00  loop=0x07ABDF00  end=0x07ABDF00
> len= 1024  scalar=0x9B97BE00  loop=0x9B97BE00  end=0x9B97BE00
> len= 4096  scalar=0x945EF800  loop=0x945EF800  end=0x945EF800
> len=16384  scalar=0xB17BE000  loop=0xB17BE000  end=0xB17BE000
> len=65536  scalar=0xC5EF8000  loop=0xC5EF8000  end=0xC5EF8000
> 
> #=== Performance ===
> 
> Implementation                len    iters      ns/call    ns/byte       MB/s
> --------------------------------------------------------------------------------
> scalar                         16    50000         7.03     0.4397    2274.46
> reduce_loop                    16    50000         2.44     0.1526    6553.29
> reduce_end                     16    50000         3.05     0.1908    5240.16
> 
> scalar                         32    50000        16.99     0.5309    1883.59
> reduce_loop                    32    50000         3.97     0.1241    8060.90
> reduce_end                     32    50000         4...

OK, I'll buy that. Performance looks good.
I think we need a comment that explains this performance, in brief, to save 
future maintainers' time. Feel free to include a link to this conversation.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/31674#discussion_r3536652264

Reply via email to