Skip to content

Faster 3-argument dot - #1367

Open
mateuszbaran wants to merge 2 commits into
masterfrom
mbaran/faster-dot-3-arg
Open

mateuszbaran wants to merge 2 commits into
masterfrom
mbaran/faster-dot-3-arg

Conversation

@mateuszbaran

Copy link
Copy Markdown
Collaborator

Solves #1287 . Selects one of three kernels: a custom SLP-vectorizable kernel, dot(x, A*y) or the the generic 3-argument dot implementation depending on the situation.

Here are my benchmark results, though it would be good to run it on other architectures to make sure the parameters are not over-tuned to a single architecture. dot(x,A*y) seems to bring most of the gains but the custom kernel is still sometimes beneficial.

Julia Version 1.13.3
Commit 67ac47b9cd8 (2026-10-25 15:28 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 16 × 12th Gen Intel(R) Core(TM) i5-12600H
  WORD_SIZE: 64
  LLVM: libLLVM-20.1.8 (ORCJIT, alderlake)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 16 virtual cores)
julia> BenchDot3.compare()
Float64
  01x01  dot(x,A,y)     1.78 ns  generic     2.01 ns  dot(x,A*y)     1.56 ns
  02x02  dot(x,A,y)     2.00 ns  generic     2.90 ns  dot(x,A*y)     1.78 ns
  02x15  dot(x,A,y)     3.63 ns  generic     8.42 ns  dot(x,A*y)     4.07 ns
  03x03  dot(x,A,y)     2.01 ns  generic     3.35 ns  dot(x,A*y)     2.48 ns
  03x08  dot(x,A,y)     3.27 ns  generic     6.01 ns  dot(x,A*y)     3.59 ns
  04x04  dot(x,A,y)     2.01 ns  generic     3.57 ns  dot(x,A*y)     2.90 ns
  04x12  dot(x,A,y)     4.11 ns  generic    10.14 ns  dot(x,A*y)     4.55 ns
  05x05  dot(x,A,y)     3.12 ns  generic     4.89 ns  dot(x,A*y)     3.41 ns
  06x06  dot(x,A,y)     2.96 ns  generic     6.70 ns  dot(x,A*y)     3.33 ns
  07x07  dot(x,A,y)     4.57 ns  generic     8.70 ns  dot(x,A*y)     4.69 ns
  08x03  dot(x,A,y)     2.58 ns  generic     4.36 ns  dot(x,A*y)     3.01 ns
  08x08  dot(x,A,y)     4.49 ns  generic    11.59 ns  dot(x,A*y)     4.94 ns
  09x09  dot(x,A,y)     6.37 ns  generic    13.95 ns  dot(x,A*y)     6.53 ns
  10x10  dot(x,A,y)     6.77 ns  generic    17.82 ns  dot(x,A*y)     7.23 ns
  11x11  dot(x,A,y)     9.11 ns  generic    19.92 ns  dot(x,A*y)     9.24 ns
  12x12  dot(x,A,y)     9.60 ns  generic    23.63 ns  dot(x,A*y)    10.04 ns
  13x13  dot(x,A,y)    13.04 ns  generic    27.13 ns  dot(x,A*y)    13.64 ns
  14x14  dot(x,A,y)    15.11 ns  generic    30.98 ns  dot(x,A*y)    16.07 ns
  15x02  dot(x,A,y)     3.94 ns  generic     5.13 ns  dot(x,A*y)     4.13 ns
  15x15  dot(x,A,y)    18.12 ns  generic    35.16 ns  dot(x,A*y)    19.13 ns
Float32
  01x01  dot(x,A,y)     1.78 ns  generic     2.23 ns  dot(x,A*y)     1.91 ns
  02x02  dot(x,A,y)     1.79 ns  generic     2.90 ns  dot(x,A*y)     2.01 ns
  02x15  dot(x,A,y)     3.61 ns  generic     8.18 ns  dot(x,A*y)     4.34 ns
  03x03  dot(x,A,y)     2.03 ns  generic     3.12 ns  dot(x,A*y)     2.67 ns
  03x08  dot(x,A,y)     2.70 ns  generic     5.35 ns  dot(x,A*y)     3.00 ns
  04x04  dot(x,A,y)     2.01 ns  generic     3.87 ns  dot(x,A*y)     2.90 ns
  04x12  dot(x,A,y)     4.01 ns  generic    10.04 ns  dot(x,A*y)     4.47 ns
  05x05  dot(x,A,y)     2.62 ns  generic     4.92 ns  dot(x,A*y)     2.94 ns
  06x06  dot(x,A,y)     2.88 ns  generic     6.69 ns  dot(x,A*y)     3.29 ns
  07x07  dot(x,A,y)     4.02 ns  generic     8.69 ns  dot(x,A*y)     4.33 ns
  08x03  dot(x,A,y)     2.46 ns  generic     4.54 ns  dot(x,A*y)     2.90 ns
  08x08  dot(x,A,y)     4.69 ns  generic    11.61 ns  dot(x,A*y)     4.96 ns
  09x09  dot(x,A,y)     6.27 ns  generic    13.93 ns  dot(x,A*y)     6.40 ns
  10x10  dot(x,A,y)     7.13 ns  generic    17.81 ns  dot(x,A*y)     7.32 ns
  11x11  dot(x,A,y)     9.43 ns  generic    19.72 ns  dot(x,A*y)     9.59 ns
  12x12  dot(x,A,y)    10.50 ns  generic    23.65 ns  dot(x,A*y)    10.75 ns
  13x13  dot(x,A,y)    12.27 ns  generic    27.34 ns  dot(x,A*y)    12.41 ns
  14x14  dot(x,A,y)    14.46 ns  generic    30.97 ns  dot(x,A*y)    14.77 ns
  15x02  dot(x,A,y)     3.91 ns  generic     5.18 ns  dot(x,A*y)     4.15 ns
  15x15  dot(x,A,y)    17.03 ns  generic    34.91 ns  dot(x,A*y)    17.23 ns
ComplexF64
  01x01  dot(x,A,y)     2.01 ns  generic     3.12 ns  dot(x,A*y)     3.12 ns
  02x02  dot(x,A,y)     2.54 ns  generic     4.54 ns  dot(x,A*y)     3.57 ns
  02x15  dot(x,A,y)    11.17 ns  generic    31.09 ns  dot(x,A*y)    20.03 ns
  03x03  dot(x,A,y)     4.39 ns  generic     8.04 ns  dot(x,A*y)     6.37 ns
  03x08  dot(x,A,y)     9.38 ns  generic    21.37 ns  dot(x,A*y)    15.45 ns
  04x04  dot(x,A,y)     7.09 ns  generic    13.29 ns  dot(x,A*y)    11.05 ns
  04x12  dot(x,A,y)    17.64 ns  generic    39.76 ns  dot(x,A*y)    27.01 ns
  05x05  dot(x,A,y)    10.45 ns  generic    19.88 ns  dot(x,A*y)    16.59 ns
  06x06  dot(x,A,y)    14.40 ns  generic    27.84 ns  dot(x,A*y)    22.00 ns
  07x07  dot(x,A,y)    19.74 ns  generic    36.59 ns  dot(x,A*y)    26.07 ns
  08x03  dot(x,A,y)    11.63 ns  generic    18.60 ns  dot(x,A*y)    15.51 ns
  08x08  dot(x,A,y)    24.79 ns  generic    46.60 ns  dot(x,A*y)    33.07 ns
  09x09  dot(x,A,y)    30.31 ns  generic    57.76 ns  dot(x,A*y)    41.23 ns
  10x10  dot(x,A,y)    37.75 ns  generic    70.73 ns  dot(x,A*y)    50.36 ns
  11x11  dot(x,A,y)    43.33 ns  generic   103.22 ns  dot(x,A*y)    61.98 ns
  12x12  dot(x,A,y)    49.25 ns  generic    72.39 ns  dot(x,A*y)    60.07 ns
  13x13  dot(x,A,y)    58.00 ns  generic   157.20 ns  dot(x,A*y)    76.72 ns
  14x14  dot(x,A,y)    64.75 ns  generic   165.42 ns  dot(x,A*y)    81.97 ns
  15x02  dot(x,A,y)    14.84 ns  generic    25.12 ns  dot(x,A*y)    17.45 ns
  15x15  dot(x,A,y)    74.89 ns  generic   180.78 ns  dot(x,A*y)   102.00 ns
ComplexF32
  01x01  dot(x,A,y)     2.01 ns  generic     2.90 ns  dot(x,A*y)     2.67 ns
  02x02  dot(x,A,y)     2.93 ns  generic     4.53 ns  dot(x,A*y)     3.12 ns
  02x15  dot(x,A,y)    16.20 ns  generic    32.54 ns  dot(x,A*y)    16.37 ns
  03x03  dot(x,A,y)     5.14 ns  generic     8.55 ns  dot(x,A*y)     5.25 ns
  03x08  dot(x,A,y)    11.66 ns  generic    22.54 ns  dot(x,A*y)    11.90 ns
  04x04  dot(x,A,y)     7.67 ns  generic    13.88 ns  dot(x,A*y)     7.71 ns
  04x12  dot(x,A,y)    21.94 ns  generic    40.88 ns  dot(x,A*y)    22.93 ns
  05x05  dot(x,A,y)    11.58 ns  generic    20.52 ns  dot(x,A*y)    11.62 ns
  06x06  dot(x,A,y)    16.47 ns  generic    27.91 ns  dot(x,A*y)    16.50 ns
  07x07  dot(x,A,y)    21.45 ns  generic    36.92 ns  dot(x,A*y)    21.77 ns
  08x03  dot(x,A,y)    12.70 ns  generic    18.41 ns  dot(x,A*y)    12.97 ns
  08x08  dot(x,A,y)    26.66 ns  generic    47.09 ns  dot(x,A*y)    26.85 ns
  09x09  dot(x,A,y)    32.63 ns  generic    58.63 ns  dot(x,A*y)    33.42 ns
  10x10  dot(x,A,y)    39.08 ns  generic    71.45 ns  dot(x,A*y)    39.35 ns
  11x11  dot(x,A,y)    54.55 ns  generic    85.20 ns  dot(x,A*y)    54.99 ns
  12x12  dot(x,A,y)    36.90 ns  generic   109.32 ns  dot(x,A*y)    38.03 ns
  13x13  dot(x,A,y)    47.26 ns  generic   105.38 ns  dot(x,A*y)    54.34 ns
  14x14  dot(x,A,y)    50.40 ns  generic   113.35 ns  dot(x,A*y)    57.84 ns
  15x02  dot(x,A,y)    15.63 ns  generic    18.25 ns  dot(x,A*y)    15.99 ns
  15x15  dot(x,A,y)    62.53 ns  generic   121.24 ns  dot(x,A*y)    79.11 ns
No regressions.
0

Contribution co-authored by Claude Opus 5.5.

@quantumsteve

Copy link
Copy Markdown

18 regressions on an Apple M5 Pro, primarily ComplexF64.

Julia Version 1.13.3
Commit 67ac47b9cd8 (2026-10-25 15:28 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: macOS (arm64-apple-darwin27.0.0)
  CPU: 18 × Apple M5 Pro
  WORD_SIZE: 64
  LLVM: libLLVM-20.1.8 (ORCJIT, apple-m1)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 18 virtual cores)
Float64
  01x01  dot(x,A,y)     0.88 ns  generic     1.33 ns  dot(x,A*y)     1.12 ns
  02x02  dot(x,A,y)     1.12 ns  generic     1.83 ns  dot(x,A*y)     1.12 ns
  02x15  dot(x,A,y)     3.00 ns  generic     6.54 ns  dot(x,A*y)     3.46 ns
  03x03  dot(x,A,y)     1.33 ns  generic     2.25 ns  dot(x,A*y)     1.79 ns
  03x08  dot(x,A,y)     2.25 ns  generic     4.08 ns  dot(x,A*y)     2.75 ns
  04x04  dot(x,A,y)     1.62 ns  generic     2.88 ns  dot(x,A*y)     2.17 ns
  04x12  dot(x,A,y)     3.38 ns  generic     7.58 ns  dot(x,A*y)     4.21 ns
  05x05  dot(x,A,y)     2.17 ns  generic     3.83 ns  dot(x,A*y)     2.67 ns
  06x06  dot(x,A,y)     2.71 ns  generic     5.17 ns  dot(x,A*y)     3.08 ns
  07x07  dot(x,A,y)     3.38 ns  generic     6.46 ns  dot(x,A*y)     3.88 ns
  08x03  dot(x,A,y)     2.08 ns  generic     3.38 ns  dot(x,A*y)     2.50 ns
  08x08  dot(x,A,y)     4.12 ns  generic     8.75 ns  dot(x,A*y)     4.54 ns
  09x09  dot(x,A,y)     4.96 ns  generic    10.46 ns  dot(x,A*y)     5.46 ns
  10x10  dot(x,A,y)     5.83 ns  generic    13.29 ns  dot(x,A*y)     6.25 ns
  11x11  dot(x,A,y)     7.25 ns  generic    15.50 ns  dot(x,A*y)     7.75 ns
  12x12  dot(x,A,y)     8.29 ns  generic    17.88 ns  dot(x,A*y)     8.58 ns
  13x13  dot(x,A,y)     8.67 ns  generic    19.45 ns  dot(x,A*y)     9.75 ns
  14x14  dot(x,A,y)    10.83 ns  generic    21.79 ns  dot(x,A*y)    11.25 ns
  15x02  dot(x,A,y)     2.54 ns  generic     3.71 ns  dot(x,A*y)     2.96 ns
  15x15  dot(x,A,y)    12.60 ns  generic    24.57 ns  dot(x,A*y)    13.22 ns
Float32
  01x01  dot(x,A,y)     1.00 ns  generic     1.12 ns  dot(x,A*y)     1.00 ns
  02x02  dot(x,A,y)     1.12 ns  generic     2.04 ns  dot(x,A*y)     1.33 ns
  02x15  dot(x,A,y)     2.08 ns  generic     6.21 ns  dot(x,A*y)     2.58 ns
  03x03  dot(x,A,y)     1.33 ns  generic     2.29 ns  dot(x,A*y)     1.71 ns
  03x08  dot(x,A,y)     2.25 ns  generic     4.04 ns  dot(x,A*y)     2.67 ns
  04x04  dot(x,A,y)     1.58 ns  generic     2.79 ns  dot(x,A*y)     1.79 ns
  04x12  dot(x,A,y)     2.50 ns  generic     7.67 ns  dot(x,A*y)     2.75 ns
  05x05  dot(x,A,y)     2.00 ns  generic     3.67 ns  dot(x,A*y)     2.42 ns
  06x06  dot(x,A,y)     2.17 ns  generic     5.21 ns  dot(x,A*y)     2.50 ns
  07x07  dot(x,A,y)     3.08 ns  generic     6.54 ns  dot(x,A*y)     3.50 ns
  08x03  dot(x,A,y)     1.92 ns  generic     3.29 ns  dot(x,A*y)     2.25 ns
  08x08  dot(x,A,y)     2.96 ns  generic     8.83 ns  dot(x,A*y)     3.33 ns
  09x09  dot(x,A,y)     4.17 ns  generic    10.50 ns  dot(x,A*y)     4.62 ns
  10x10  dot(x,A,y)     4.25 ns  generic    13.26 ns  dot(x,A*y)     4.46 ns
  11x11  dot(x,A,y)     5.62 ns  generic    15.39 ns  dot(x,A*y)     5.96 ns
  12x12  dot(x,A,y)     6.08 ns  generic    17.52 ns  dot(x,A*y)     6.12 ns
  13x13  dot(x,A,y)     7.62 ns  generic    19.71 ns  dot(x,A*y)     7.71 ns
  14x14  dot(x,A,y)     8.92 ns  generic    21.83 ns  dot(x,A*y)     9.04 ns
  15x02  dot(x,A,y)     2.71 ns  generic     3.54 ns  dot(x,A*y)     2.96 ns
  15x15  dot(x,A,y)    10.50 ns  generic    24.25 ns  dot(x,A*y)    10.88 ns
ComplexF64
  01x01  dot(x,A,y)     1.25 ns  generic     1.71 ns  dot(x,A*y)     1.67 ns
  02x02  dot(x,A,y)     2.21 ns  generic     2.92 ns  dot(x,A*y)     2.71 ns
  02x15  dot(x,A,y)    12.18 ns  generic    20.71 ns  dot(x,A*y)    10.50 ns  <-- regression
  03x03  dot(x,A,y)     4.71 ns  generic     5.46 ns  dot(x,A*y)     5.67 ns
  03x08  dot(x,A,y)    10.75 ns  generic    14.71 ns  dot(x,A*y)     7.38 ns  <-- regression
  04x04  dot(x,A,y)     7.38 ns  generic     8.62 ns  dot(x,A*y)     5.71 ns  <-- regression
  04x12  dot(x,A,y)    20.88 ns  generic    27.62 ns  dot(x,A*y)    14.75 ns  <-- regression
  05x05  dot(x,A,y)    11.43 ns  generic    13.76 ns  dot(x,A*y)     8.75 ns  <-- regression
  06x06  dot(x,A,y)    16.67 ns  generic    19.50 ns  dot(x,A*y)    12.17 ns  <-- regression
  07x07  dot(x,A,y)    22.21 ns  generic    25.92 ns  dot(x,A*y)    16.00 ns  <-- regression
  08x03  dot(x,A,y)    11.72 ns  generic    11.67 ns  dot(x,A*y)     9.58 ns  <-- regression
  08x08  dot(x,A,y)    32.33 ns  generic    33.35 ns  dot(x,A*y)    20.08 ns  <-- regression
  09x09  dot(x,A,y)    40.75 ns  generic    41.71 ns  dot(x,A*y)    24.32 ns  <-- regression
  10x10  dot(x,A,y)    49.61 ns  generic    50.71 ns  dot(x,A*y)    29.54 ns  <-- regression
  11x11  dot(x,A,y)    56.05 ns  generic    57.22 ns  dot(x,A*y)    32.68 ns  <-- regression
  12x12  dot(x,A,y)    52.81 ns  generic    53.76 ns  dot(x,A*y)    40.87 ns  <-- regression
  13x13  dot(x,A,y)    66.47 ns  generic    75.22 ns  dot(x,A*y)    51.80 ns  <-- regression
  14x14  dot(x,A,y)    75.85 ns  generic    76.73 ns  dot(x,A*y)    62.01 ns  <-- regression
  15x02  dot(x,A,y)    15.83 ns  generic    13.26 ns  dot(x,A*y)    17.27 ns  <-- regression
  15x15  dot(x,A,y)    86.70 ns  generic    99.00 ns  dot(x,A*y)    61.80 ns  <-- regression
ComplexF32
  01x01  dot(x,A,y)     1.29 ns  generic     2.00 ns  dot(x,A*y)     1.79 ns
  02x02  dot(x,A,y)     2.04 ns  generic     2.96 ns  dot(x,A*y)     2.38 ns
  02x15  dot(x,A,y)    12.76 ns  generic    21.71 ns  dot(x,A*y)    12.85 ns
  03x03  dot(x,A,y)     3.79 ns  generic     5.54 ns  dot(x,A*y)     3.79 ns
  03x08  dot(x,A,y)     8.00 ns  generic    14.72 ns  dot(x,A*y)     8.08 ns
  04x04  dot(x,A,y)     5.83 ns  generic     8.96 ns  dot(x,A*y)     6.04 ns
  04x12  dot(x,A,y)    17.21 ns  generic    27.18 ns  dot(x,A*y)    17.46 ns
  05x05  dot(x,A,y)     9.08 ns  generic    13.33 ns  dot(x,A*y)     9.04 ns
  06x06  dot(x,A,y)    12.00 ns  generic    18.50 ns  dot(x,A*y)    12.21 ns
  07x07  dot(x,A,y)    16.35 ns  generic    24.46 ns  dot(x,A*y)    16.29 ns
  08x03  dot(x,A,y)    10.17 ns  generic    11.54 ns  dot(x,A*y)    10.17 ns
  08x08  dot(x,A,y)    21.59 ns  generic    31.08 ns  dot(x,A*y)    21.54 ns
  09x09  dot(x,A,y)    27.00 ns  generic    38.36 ns  dot(x,A*y)    26.89 ns
  10x10  dot(x,A,y)    34.05 ns  generic    46.91 ns  dot(x,A*y)    34.06 ns
  11x11  dot(x,A,y)    40.45 ns  generic    55.92 ns  dot(x,A*y)    40.83 ns
  12x12  dot(x,A,y)    41.67 ns  generic    35.46 ns  dot(x,A*y)    48.73 ns  <-- regression
  13x13  dot(x,A,y)    52.56 ns  generic    76.57 ns  dot(x,A*y)    63.13 ns
  14x14  dot(x,A,y)    54.57 ns  generic    88.47 ns  dot(x,A*y)    72.28 ns
  15x02  dot(x,A,y)    13.79 ns  generic    13.47 ns  dot(x,A*y)    13.89 ns
  15x15  dot(x,A,y)    62.77 ns  generic   100.45 ns  dot(x,A*y)    78.54 ns
18 regression(s).

@mateuszbaran

Copy link
Copy Markdown
Collaborator Author

Thanks for testing, I've modified the code to select the dot(x, A*y) implementation for non-x86 targets in that case.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants