Repository navigation
cpu: accept BF16 in src1 of mul_mat - #28937
Conversation
|
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. |
|
Thanks for working on this follow-up and adding a test. :) |
|
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! |
|
I'll look into it. |
|
That's actually better, and I would just run the Vulkan correctness on the model |
d05aadd to
fa5e7cd
Compare
|
Rebase only |
03e40df to
e053886
Compare
|
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.
e053886 to
743bd31
Compare
|
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 |
* 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.
* 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.
* 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)
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:
F32 x BF16 per backend:
Requirements