Skip to content

cpu: accept BF16 in src1 of mul_mat - #28937

Merged
ServeurpersoCom merged 2 commits into
ggml-org:masterfrom
ServeurpersoCom:cpu-mul-mat-bf16-src1
Sep 30, 2026
Merged

ServeurpersoCom merged 2 commits into
ggml-org:masterfrom
ServeurpersoCom:cpu-mul-mat-bf16-src1

Conversation

@ServeurpersoCom

@ServeurpersoCom ServeurpersoCom commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Overview

ggml_mul_mat already handles BF16 x F32 and BF16 x BF16, but not the mirror case F32 x BF16, which is exactly what ggml_conv_1d_dw produces with a BF16 kernel. This fills that cell on the CPU, with the tests that were missing.

Additional information

CPU reference for #28741: test-backend-ops only compares a case that both the tested backend and the CPU declare supported, so this cell was reported as not supported everywhere and the Metal kernels had nothing to be checked against. CUDA already runs it and #28741 adds it to Metal, but the reference backend does not.

BF16 in ggml_mul_mat on the CPU:

src0 src1 before after
BF16 F32 ok ok
BF16 BF16 ok ok
F32 BF16 not supported ok

F32 x BF16 per backend:

backend status
CUDA supported, cuBLAS widens src1 to F32
Metal supported with #28741 (mul_mv)
CPU this PR

Requirements

@github-actions github-actions Bot added testing Everything test related ggml changes relating to the ggml tensor library for machine learning labels Sep 15, 2026
@ServeurpersoCom
ServeurpersoCom requested a review from a team as a code owner September 15, 2026 17:28
@github-actions github-actions Bot added the Vulkan Issues specific to the Vulkan backend label Sep 15, 2026
@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

The BF16 kernel case of the conv_1d_dw test exercises the f32 x bf16 mat vec path on Metal, which only exists in #28741; the gpu-metal job goes green once that one is merged and this branch is rebased.

@nikwen

nikwen commented Sep 16, 2026

Copy link
Copy Markdown
Member

Thanks for working on this follow-up and adding a test. :)

@0cc4m

0cc4m commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Is this used for something, so would it be worth adding support to Vulkan? If so I can do that.

@ServeurpersoCom

ServeurpersoCom commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor Author

Is this used for something, so would it be worth adding support to Vulkan? If so I can do that.

Yes, I hit it on an unreleased LLM with an audio input tower: its depthwise conv kernels are BF16, so ggml_conv_1d_dw lands on f32 x bf16.

Anything audio ML is something I end up using sooner or later, so I'd love for GGML to have no holes in this op matrix, it's more future proof. A Vulkan path would be great if you're up for it!

I also have Vulkan on hand (windows/linux), so if you prefer I can write it myself, keeping it strictly symmetric with the existing BF16 paths, and validate it on the real model with cosine similarity against the CPU reference, leaving you just the review. Whichever you prefer!

@0cc4m

0cc4m commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

I'll look into it.

@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

That's actually better, and I would just run the Vulkan correctness on the model

@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

Rebase only

@ServeurpersoCom
ServeurpersoCom force-pushed the cpu-mul-mat-bf16-src1 branch 2 times, most recently from 03e40df to e053886 Compare September 27, 2026 17:33
@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

Rebase after the merge of #29365, which fixes the Vulkan misalignment assert that broke the previous CI run.

Tested locally on an RTX PRO 6000:

ggml_conv_1d_dw builds its im2col in F32 when the kernel is BF16, then
calls ggml_mul_mat(im2col, kernel), which puts F32 in src0 and BF16 in
src1. The CPU backend refused that combination, so it was reported as
unsupported on every backend and never compared against anything.

Widen BF16 into the F32 work buffer, next to the existing packing of F32
into vec_dot_type. This is the arithmetic the Metal mat vec kernel
already uses, both operands promoted to float and accumulated in float,
so the two agree exactly rather than approximately.

Cover it with a conv_1d_dw test over F32, F16 and BF16 kernels, plus
three mul_mat cases with BF16 in src1.
supports_op only checked the src1 type for non contiguous tensors, so
a contiguous BF16 src1 was accepted and the pipeline lookup asserted.
The only BF16 src1 path is the BF16 x BF16 multiply, every other src0
type now reports the op as unsupported and the scheduler keeps it on
the CPU.

The BF16 kernel case of the conv_1d_dw test needs the f32 x bf16
mat vec variants of the Metal backend, which land separately.
@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

The red jobs are unrelated: Metal fusion is the missing glm5-next baseline fixed by #29712, WebGPU is red on master, and the Vulkan Intel and OpenVINO failures are tolerance misses on SET_ROWS q2_0 and ADD_ADD f16, with no MUL_MAT failure anywhere. Merging

@ServeurpersoCom
ServeurpersoCom merged commit 90c908d into ggml-org:master Sep 30, 2026
29 of 34 checks passed
pierreguillot pushed a commit to Ircam-Partiels/llama.cpp that referenced this pull request Oct 1, 2026
* cpu: accept BF16 in src1 of mul_mat

ggml_conv_1d_dw builds its im2col in F32 when the kernel is BF16, then
calls ggml_mul_mat(im2col, kernel), which puts F32 in src0 and BF16 in
src1. The CPU backend refused that combination, so it was reported as
unsupported on every backend and never compared against anything.

Widen BF16 into the F32 work buffer, next to the existing packing of F32
into vec_dot_type. This is the arithmetic the Metal mat vec kernel
already uses, both operands promoted to float and accumulated in float,
so the two agree exactly rather than approximately.

Cover it with a conv_1d_dw test over F32, F16 and BF16 kernels, plus
three mul_mat cases with BF16 in src1.

* vulkan: reject BF16 in src1 of mul_mat unless src0 is BF16

supports_op only checked the src1 type for non contiguous tensors, so
a contiguous BF16 src1 was accepted and the pipeline lookup asserted.
The only BF16 src1 path is the BF16 x BF16 multiply, every other src0
type now reports the op as unsupported and the scheduler keeps it on
the CPU.

The BF16 kernel case of the conv_1d_dw test needs the f32 x bf16
mat vec variants of the Metal backend, which land separately.
frostyautumnleaf pushed a commit to frostyautumnleaf/llama.cpp that referenced this pull request Oct 5, 2026
* cpu: accept BF16 in src1 of mul_mat

ggml_conv_1d_dw builds its im2col in F32 when the kernel is BF16, then
calls ggml_mul_mat(im2col, kernel), which puts F32 in src0 and BF16 in
src1. The CPU backend refused that combination, so it was reported as
unsupported on every backend and never compared against anything.

Widen BF16 into the F32 work buffer, next to the existing packing of F32
into vec_dot_type. This is the arithmetic the Metal mat vec kernel
already uses, both operands promoted to float and accumulated in float,
so the two agree exactly rather than approximately.

Cover it with a conv_1d_dw test over F32, F16 and BF16 kernels, plus
three mul_mat cases with BF16 in src1.

* vulkan: reject BF16 in src1 of mul_mat unless src0 is BF16

supports_op only checked the src1 type for non contiguous tensors, so
a contiguous BF16 src1 was accepted and the pipeline lookup asserted.
The only BF16 src1 path is the BF16 x BF16 multiply, every other src0
type now reports the op as unsupported and the scheduler keeps it on
the CPU.

The BF16 kernel case of the conv_1d_dw test needs the f32 x bf16
mat vec variants of the Metal backend, which land separately.
edwardyoon pushed a commit to edwardyoon/focus-llama that referenced this pull request Oct 7, 2026
* cpu: accept BF16 in src1 of mul_mat

ggml_conv_1d_dw builds its im2col in F32 when the kernel is BF16, then
calls ggml_mul_mat(im2col, kernel), which puts F32 in src0 and BF16 in
src1. The CPU backend refused that combination, so it was reported as
unsupported on every backend and never compared against anything.

Widen BF16 into the F32 work buffer, next to the existing packing of F32
into vec_dot_type. This is the arithmetic the Metal mat vec kernel
already uses, both operands promoted to float and accumulated in float,
so the two agree exactly rather than approximately.

Cover it with a conv_1d_dw test over F32, F16 and BF16 kernels, plus
three mul_mat cases with BF16 in src1.

* vulkan: reject BF16 in src1 of mul_mat unless src0 is BF16

supports_op only checked the src1 type for non contiguous tensors, so
a contiguous BF16 src1 was accepted and the pipeline lookup asserted.
The only BF16 src1 path is the BF16 x BF16 multiply, every other src0
type now reports the op as unsupported and the scheduler keeps it on
the CPU.

The BF16 kernel case of the conv_1d_dw test needs the f32 x bf16
mat vec variants of the Metal backend, which land separately.

(cherry picked from commit 90c908d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ggml changes relating to the ggml tensor library for machine learning testing Everything test related Vulkan Issues specific to the Vulkan backend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants