Skip to content

metal: implement OUR_PROD for F32 - #28162

Open
HankBO wants to merge 1 commit into
ggml-org:masterfrom
HankBO:support-mtl-out-prod
Open

metal: implement OUR_PROD for F32#28162
HankBO wants to merge 1 commit into
ggml-org:masterfrom
HankBO:support-mtl-out-prod

Conversation

@HankBO

@HankBO HankBO commented Sep 1, 2026

Copy link
Copy Markdown

Overview

Support OUT_PROD op partially for metal backend: <F32, F32>.

Add test cases for OUT_PROD performance testing.

ref #14909. close my previous PR #23724 and open a new one to focus on f32.

Additional information

ran testing command with build/bin/test-backend-ops test -o OUT_PROD -b MTL0 and all test cases passed on my m4 air.

Testing 3 devices

Backend 1/3: MTL0
  Device description: Apple M4
  Device memory: 18186 MB (18185 MB free)

  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[1,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=1,bs=[3,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[1,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=1,k=16,bs=[3,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[1,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=1,bs=[3,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[1,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,1],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,1],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,1],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,1],nr=[2,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,3],nr=[1,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,3],nr=[1,2],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,3],nr=[2,1],trans_b=0): �[1;32mOK�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=256,n=16,k=16,bs=[3,3],nr=[2,2],trans_b=0): �[1;32mOK�[0m

did comparison with my perf testing case ./bin/test-backend-ops perf -o OUT_PROD -b MTL0, build/bin/test-backend-ops perf -o OUT_PROD -b CPU

Testing 3 devices

Backend 1/3: MTL0
  Device description: Apple M4
  Device memory: 18186 MB (18185 MB free)

  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=32,bs=[1,1],nr=[1,1],trans_b=0):                7654 runs -   194.66 us/run -     8768 kB/run - �[1;34m  42.96 GB/s�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=64,bs=[1,1],nr=[1,1],trans_b=0):                3592 runs -   326.16 us/run -     9344 kB/run - �[1;34m  27.32 GB/s�[0m
  Backend MTL0: �[1;32mOK�[0m
Backend 2/3: BLAS
  Device description: Accelerate
  Device memory: 0 MB (0 MB free)

  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=32,bs=[1,1],nr=[1,1],trans_b=0):                3827 runs -   314.65 us/run -     8768 kB/run - �[1;34m  26.57 GB/s�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=64,bs=[1,1],nr=[1,1],trans_b=0):                3592 runs -   398.90 us/run -     9344 kB/run - �[1;34m  22.34 GB/s�[0m
  Backend BLAS: �[1;32mOK�[0m
Backend 3/3: CPU
  Skipping CPU backend
3/3 backends passed
�[1;32mOK�[0m

Testing 3 devices

Backend 1/3: MTL0
  Skipping
Backend 2/3: BLAS
  Skipping
Backend 3/3: CPU
  Device description: Apple M4
  Device memory: 24576 MB (24576 MB free)

  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=32,bs=[1,1],nr=[1,1],trans_b=0):                 957 runs -  3108.74 us/run -     8768 kB/run - �[1;34m   2.69 GB/s�[0m
  OUT_PROD(type_a=f32,type_b=f32,m=4096,n=512,k=64,bs=[1,1],nr=[1,1],trans_b=0):                 898 runs -  6023.31 us/run -     9344 kB/run - �[1;34m   1.48 GB/s�[0m
  Backend CPU: �[1;32mOK�[0m
3/3 backends passed
�[1;32mOK�[0m

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: Yes, I used AI to help me learn the codebase, and refine my coding. I do the design and implementation by myself.

@HankBO
HankBO requested review from a team and ggerganov as code owners September 1, 2026 11:31
@github-actions github-actions Bot added testing Everything test related ggml changes relating to the ggml tensor library for machine learning Apple Metal https://en.wikipedia.org/wiki/Metal_(API) labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Apple Metal https://en.wikipedia.org/wiki/Metal_(API) ggml changes relating to the ggml tensor library for machine learning testing Everything test related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant