Skip to content

ggml-cpu: write matmul results straight into dst in the nrows==1 fast path - #50

Open
codspeed-hq[bot] wants to merge 1 commit into
masterfrom
codspeed-optim-write-matmul-results-straight-into-dst-and-drop-th-1785470631492
Open

ggml-cpu: write matmul results straight into dst in the nrows==1 fast path#50
codspeed-hq[bot] wants to merge 1 commit into
masterfrom
codspeed-optim-write-matmul-results-straight-into-dst-and-drop-th-1785470631492

Conversation

@codspeed-hq

@codspeed-hq codspeed-hq Bot commented Jul 31, 2026

Copy link
Copy Markdown

What

Every output element of a CPU matmul goes through ggml_compute_forward_mul_mat_one_chunk(). The loop around the vec_dot call carries per-element overhead unrelated to the arithmetic:

  • results are staged in a float tmp[32] buffer and copied to dst with a libc memcpy call per column,
  • the vec_dot arguments are rebuilt from num_rows_per_vec_dot > 1 ? … : … conditionals on every call (3 cmovs per call),
  • the (i11, i12, i13) column indices are recomputed with two 64-bit divisions per column.

num_rows_per_vec_dot == 1 for every kernel except the ARM mmla ones, so this adds a dedicated fast path for it:

  • the results of a row block are written straight into dst — a chunk owns those elements exclusively, and the existing comment notes the staging buffer (a false-sharing experiment) "does not seem to make a difference",
  • the vec_dot arguments become compile-time constants,
  • the column indices are carried across the block instead of being divided out per column.

The generic num_rows_per_vec_dot > 1 path is untouched.

Correctness — bit-identical

The arithmetic is unchanged (same kernel, same operands, same order). Verified against a build of the unmodified tree: 160 cases byte-for-byte identical — F32/F16/Q8_0/Q4_0/Q4_K × 8 shapes (including odd M/N/K, partial blocks, single-column shapes and broadcast ne2/ne3) × 1/2/5/8 threads.

Test suite (built from this branch, CPU backend):

  • test-backend-ops test -o MUL_MAT — OK
  • test-opt, test-quantize-fns, test-rope, test-barrier, test-alloc, test-gguf, test-col2im-1d — all pass

Measured (CodSpeed, CPU simulation, micro suite)

Simulation is deterministic here — 11 of the 15 benchmarks are byte-identical between the two runs, so the noise floor is ~0.

Benchmark Base Head Δ
mul_mat[q4_k] 71.72 ms 70.72 ms −1.4%
mul_mat[q4_0] 101.91 ms 100.85 ms −1.0%
mul_mat[f32] 346.97 ms 345.96 ms −0.3%
ffn_swiglu 1.07 s 1.07 s

No regressions on any of the 15 micro benchmarks.

Caveats

  • This is a small win in simulation (~1–2% on quantized matmul, less on F32 where each vec_dot call does far more work per call).
  • The simulation instrument counts instructions, so it under-weights exactly what this removes: a 64-bit div costs ~30 cycles but counts as one instruction, and a libc memcpy call counts as a handful. The walltime macro job should therefore show a larger gain than the numbers above.
  • No new memory, no change to threading or chunking.

… path

Add a dedicated path in ggml_compute_forward_mul_mat_one_chunk() for
num_rows_per_vec_dot == 1, which covers every kernel except the ARM mmla
ones. It writes the vec_dot results directly into dst instead of staging
them in a tmp buffer and memcpy-ing one column at a time, passes constant
vec_dot arguments instead of rebuilding them from conditionals on every
call, and carries the (i11, i12, i13) column indices across a row block
instead of recomputing them with 64-bit divisions per column.

The generic num_rows_per_vec_dot > 1 path is unchanged, and results are
bit-identical.
@github-actions github-actions Bot added the ggml label Jul 31, 2026
@codspeed-hq

codspeed-hq Bot commented Jul 31, 2026

Copy link
Copy Markdown
Author

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codspeed-optim-write-matmul-results-straight-into-dst-and-drop-th-1785470631492 (602d071) with master (46819c9)

Open in CodSpeed

@codspeed-hq
codspeed-hq Bot marked this pull request as ready for review July 31, 2026 04:49
@codspeed-hq
codspeed-hq Bot requested a review from coco-speed July 31, 2026 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant