On Thu, 13 Aug 2026 22:48:49 GMT, Chad Rakoczy <[email protected]> wrote:

> Adds support for vectorized dot product on aarch64 (`sdot` and `udot`) 
> through the Vector API
> 
> Dedicated dot product instructions have been shown to provide up to 10x 
> throughput for lucene 
> ([results](https://github.com/apache/lucene/pull/13572)) compared to 
> vectorized multiply and add. This PR adds two new methods to `ByteVector` to 
> leverage the aarch dot product instructions `sdot` and `udot` respectively.
> - `IntVector dot(Vector<Byte> v, Vector<Integer> acc)`
> - `IntVector dotUnsigned(Vector<Byte> v, Vector<Integer> acc)`
> 
> Each int lane of the result holds the dot product of the corresponding group 
> of four bytes from the two operands, added to the matching accumulator lane. 
> For example:
> 
> a = [a1, a2, a3, a4, ..., ..., a13, a14, a15, a16]
> b = [b1, b2, b3, b4, ..., ..., b13, b14, b15, b16]
> acc = [acc1, ..., ..., acc4]
> 
> a.dot(b, acc) -> [
>     acc1 + a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4, 
>     ..., 
>     ...,
>     acc4 + a13 * b13 + a14 * b14 + a15 * b15 + a16 * b16
> ]
> 
> 
> The equivalent instructions on x86 are `VPDPBSSD` and `VPDPBUUD` which 
> perform the same operations and match the proposed new functions however this 
> PR only includes aarch64.
> 
> Graviton 2
> 
> Benchmark                              Mode  Cnt      Score     Error   Units
> VectorDotBenchmark.dotScalar          thrpt   25   2412.719 ±   0.014  ops/ms
> VectorDotBenchmark.dotMulAdd          thrpt   25   1497.953 ±   2.734  ops/ms
> VectorDotBenchmark.dotVector          thrpt   25  23243.016 ± 141.708  ops/ms
> VectorDotBenchmark.dotUnsignedScalar  thrpt   25   2402.966 ±   0.157  ops/ms
> VectorDotBenchmark.dotUnsignedMulAdd  thrpt   25   1498.898 ±   1.442  ops/ms
> VectorDotBenchmark.dotUnsignedVector  thrpt   25  23344.116 ± 222.150  ops/ms
> 
> 
> Graviton 3
> 
> Benchmark                              Mode  Cnt      Score     Error   Units
> VectorDotBenchmark.dotScalar          thrpt   25   7946.950 ±   2.564  ops/ms
> VectorDotBenchmark.dotMulAdd          thrpt   25   3257.311 ±   5.308  ops/ms
> VectorDotBenchmark.dotVector          thrpt   25  41430.996 ± 688.936  ops/ms
> VectorDotBenchmark.dotUnsignedScalar  thrpt   25   2536.268 ±   0.438  ops/ms
> VectorDotBenchmark.dotUnsignedMulAdd  thrpt   25   3259.853 ±   3.511  ops/ms
> VectorDotBenchmark.dotUnsignedVector  thrpt   25  41263.821 ± 478.856  ops/ms
> 
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

I'd still recommend to separate implementation and API work. Even though 
matching vector operation shapes is brittle compared to dedicated API point, it 
still exposes the desired functionality for potential users to try it out.      

Unfortunately, I don't see a clear path to expose SVE/AVX512-VNNI instructions 
through Vector API as it is shaped now. 
There's no precedent vector operation shape (yet?) to match them well. There 
are multiple reasons why they can be considered "snowflakes": applicable only 
for subword element types (8-/16-bit in size), mixture of signed & unsigned 
operands, mixture of subword operands and word-sized result (ByteVector x 
ByteVector -> IntVector operation). Even though both AArch64 and AVX512 feature 
similar instructions, it doesn't make the operations themselves less adhoc. 

So, as the stop-the-gap solution, matching enables access to desired 
functionality while giving more time to explore possible approaches on API 
side.  

> I made an attempt at rewriting the routine from @iwanowww , but with the 
> actual dot product routine behaviour. The SVE *DOT instructions calculate the 
> dot product of 4 groups of 4 bytes from two vectors and store the results 
> into 4x 32-bit lanes. For vectors longer that 128-bits, this is repeated over 
> however many 128-bit slices there are in a vector:

FTR I deliberately avoided exposing accumulator as a vector. Proposed version 
gives enough freedom for JIT-compiler to generate efficient code (reordering 
associative operations, plus transforming sum of reductions to reduction on a 
vector accumulator may be used to match even naive implementation to the 
particular machine instruction).

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

PR Comment: https://git.openjdk.org/jdk/pull/32359#issuecomment-6156124073

Reply via email to