[MLAS][KleidiAI] Add MatMul, Gemm, and Conv FP16 execution paths - #29709
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
7d86dcb to
37a0249
Compare
There was a problem hiding this comment.
Pull request overview
This PR wires newly introduced MLAS FP16 (HalfGemm + backend-native packed-B + HalfConv) capabilities into the CPU Execution Provider’s MatMul, Gemm, and FP16 Conv kernels, including prepacking behavior and tests, and updates operator docs to advertise FP16 support.
Changes:
- Registers CPU
MLFloat16kernels forMatMulandGemmacross multiple opset ranges, and routes FP16 execution through MLAS (MlasHalfGemmBatch) with backend-selector propagation and optional backend-native B prepacking. - Extends FP16 CPU
Convto opportunistically use MLAS HalfConv (including optional constant bias baking into a session-local packed buffer), while keeping generic prepacked weights shareable across sessions. - Strengthens prepacking validation by adding an explicit “kernel-owned packed weights” marker and adding coverage for broken prepack implementations and sharing behavior.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc | Adds FP16 Conv tests covering HalfConv eligibility, bias/no-bias, and KleidiAI disable fallback. |
| onnxruntime/test/providers/cpu/math/matmul_test.cc | Adds test coverage for kernel-owned FP16 MatMul prepacking not entering shared prepack cache. |
| onnxruntime/test/providers/cpu/math/gemm_test.cc | Adds FP16 Gemm tests for “missing C” and beta == 0 cases. |
| onnxruntime/test/mlas/unittest/test_halfgemm.h | Updates unit test for updated HalfGemm override signature. |
| onnxruntime/test/mlas/unittest/test_halfgemm.cpp | Updates override signature and related KleidiAI HalfGemm tests to match new API. |
| onnxruntime/test/framework/session_state_test.cc | Adds a broken-prepack kernel and a test validating session-state rejects non-cacheable successful prepack. |
| onnxruntime/core/util/math_cpu.cc | Adds MatMul<MLFloat16> specialization that uses MlasHalfGemmBatch when available. |
| onnxruntime/core/providers/cpu/math/matmul.h | Introduces MatMul<MLFloat16> kernel with backend selector + prepack plumbing. |
| onnxruntime/core/providers/cpu/math/matmul.cc | Registers FP16 MatMul kernels, implements MLAS-backed FP16 MatMul compute + backend-native packed-B prepack. |
| onnxruntime/core/providers/cpu/math/gemm.cc | Extends FP16 Gemm MLAS path to support no-bias (beta==0) and MLAS-compatible bias shapes. |
| onnxruntime/core/providers/cpu/fp16/fp16_conv.cc | Adds MLAS HalfConv fast path, including session-local packed weights+bias handling. |
| onnxruntime/core/providers/cpu/cpu_execution_provider.cc | Registers FP16 MatMul/Gemm kernel class declarations and creation entries for CPU EP. |
| onnxruntime/core/mlas/lib/mlasi.h | Updates KleidiAI HalfGemm override signature to drop explicit selector config parameter. |
| onnxruntime/core/mlas/lib/kleidiai/mlasi_kleidiai.h | Updates KleidiAI header declaration for updated override signature. |
| onnxruntime/core/mlas/lib/kleidiai/halfgemm_kleidiai.cpp | Removes redundant per-call selector check; relies on centralized dispatcher gating. |
| onnxruntime/core/mlas/lib/halfgemm.cpp | Centralizes backend selector handling before calling platform override. |
| onnxruntime/core/framework/session_state.cc | Updates prepack validation to allow explicit kernel-owned packed weights marker. |
| onnxruntime/core/framework/prepacked_weights.h | Adds has_kernel_owned_packed_weights_ marker to PrePackedWeights. |
| onnxruntime/core/framework/prepacked_weights_container.cc | Ensures the kernel-owned packed marker is preserved in referring copies. |
| onnxruntime/contrib_ops/cpu/moe/moe_cpu.cc | Updates HalfGemm params initialization style ({}) consistent with new patterns. |
| docs/OperatorKernels.md | Updates documentation to list FP16 support for CPU MatMul and Gemm. |
3aeb947 to
00de02c
Compare
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Re-review: PR #29709 — [MLAS][KleidiAI] Add MatMul, Gemm, and Conv FP16 execution paths (head
|
Head branch was pushed to by a user without write access
Review: PR #29709 — [MLAS][KleidiAI] Add MatMul, Gemm, and Conv FP16 execution paths (head
|
Register CPU fp16 MatMul/Gemm kernels and route fp16 Conv through the native half-conv/prepack paths using the MLAS APIs from the previous branch. This carries the current branch session_state.cc relaxation as WIP; the maintainer-requested sentinel modeling for backend-owned prepack buffers still needs to replace it before review. Source-commit: 923422f Source-commit: a504a0c Source-commit: 152ef31 Source-commit: b81f7ab9f2e35b85d9e4f825c31aa4ddaad7e875 Signed-off-by: Cathal Lawlor <cathal.lawlor@arm.com>
Introduce an explicit kernel-owned packed-weights marker so fp16 MatMul can report successful backend-owned prepacking without relaxing the existing shared prepack invariant for broken kernels. Update fp16 MatMul, Gemm, Conv, Moe, and MLAS test call sites for the branch-2 half-GEMM API shape where backend selector config is carried through MLAS_HALF_GEMM_DATA_PARAMS. Clarify HalfConv working-buffer sizing as bytes, zero-initialize MLAS_CONV_PARAMETERS, and add/adjust tests for the fp16 MatMul kernel-owned prepack path, broken prepack invariant, half-GEMM selector handling, and HalfConv byte-size reporting. Signed-off-by: Cathal Lawlor <cathal.lawlor@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
467007c to
385bdf1
Compare
Pass-3 re-review: PR #29709 — [MLAS][KleidiAI] Add MatMul, Gemm, and Conv FP16 execution paths (head
|
| # | SHA | Title | Since pass |
|---|---|---|---|
| 1 | b25c723 |
Add CPU EP fp16 MatMul Gemm and Conv prepack paths (main) | pass-1 base |
| 2 | 1642972 |
Address CPU fp16 prepack review feedback | pass-1 |
| 3 | c8aa059 |
Address review feedback | pass-2 |
| 4 | 0031eaa |
Address CPU FP16 review feedback | pass-2 |
| 5 | 0cd6d71 |
Align expanded FP16 attention tolerances | new |
| 6 | 7d97b21 |
Fix CPU FP16 MatMul fallback and test tolerance | new |
| 7 | 385bdf1 |
Fix CPU FP16 Gemm fallback dispatch | new (head) |
CI: 1 / 68 checks OK on 385bdf1 — pipelines just spun up on the force-push, too early to draw conclusions. Pre-push (at pass-2 heads 467007c and 3ef65e5) the same code was at 35-83 / 78-86 depending on stage. Force-push also auto-dismissed @hariharans29's previous approval — the PR now shows "At least 1 approving review is required to merge."
Verdict: pass-2 approval stands. The three new commits are targeted follow-ups to CI failures I explicitly flagged as the most likely regression source in pass-2, and they land exactly where I said to look. Re-request approval from @hariharans29 and merge when CI settles.
Delta from pass-2 head (467007c) — three targeted fixes
Commit 5 (0cd6d71): "Align expanded FP16 attention tolerances" — proactive follow-up to pass-2 nit. My pass-2 flagged:
If any of the three [
_expandedoverrides in onnx_backend_test_series_overrides.jsonc] flakes post-merge, a one-line bump is the fix.
This commit aligns the tolerances before waiting for a flake. Sensible.
Commit 6 (7d97b21): "Fix CPU FP16 MatMul fallback and test tolerance" — targeted fix. My pass-2 explicitly called out:
If any leg lands as a fail rather than pending, the three latest fallback fixes are the likely suspects to check first — they touch dispatch paths that a CPU-FP16-heavy test could probe.
This commit fixes the MatMul<MLFloat16>::Compute fallback path — one of the exact three sites where the MlasFp16AccelerationSupported() || MlasHalfGemmNativePackBSize(...) != 0 gate was added in pass-2. Along with a test tolerance update.
Commit 7 (385bdf1): "Fix CPU FP16 Gemm fallback dispatch" — same shape for Gemm_MLFloat16. Second of the three sites. Consistent with commit 6.
The pattern (fix MatMul fallback → fix Gemm fallback) suggests CI on the pass-2 head caught an issue in the runtime-FP16-gating check on some non-FEAT_FP16 leg, and these two commits are the surgical fixes. Given the pass-2 correctness argument for those sites was fundamentally sound (the fix went from unconditional Neon dispatch → runtime probe + Eigen fallback), the follow-up here is likely a corner case in how the probe/fallback interacts with the pre-packed-B path or a specific test's assumptions about the dispatched kernel.
Without the specific diff content for those two commits, I can't rule out that they introduce a design-level change, but the commit titles and small-scope naming (Fix ... fallback, Fix ... dispatch) strongly suggest one-site-per-file surgical fixes rather than architectural revisions.
Everything from passes 1 and 2 still stands
Design substance unchanged since pass-2:
has_kernel_owned_packed_weights_marker onPrePackedWeights— clean opt-out from cross-session sharing. Consumed insession_state.ccviaORT_RETURN_IF_NOT(!buffers.empty() || has_kernel_owned_packed_weights_, ...). Container insertion guarded on!has_kernel_owned_packed_weights_. Defaultfalseso every existing kernel is unaffected.MatMul<MLFloat16>opts out by design —PrePacksets the marker;UseSharedPrePackedBuffersreturnsused_shared_buffers = false. Conservative-but-correct choice given FP16 packed-B layout opacity across KleidiAI vs. non-KleidiAI backends.- Conv HalfConv weights+bias combined pack — bias baked in only when
!share_prepacked_weights, correctly preventing W-hash-collision-based cross-session bias adoption. - Latent HalfGemm dispatch bug fix in
halfgemm.h— added runtimeHasFp16VectorAcceleration()probe. Real correctness fix. MatmulTransposeFusionCPU-FP16 exclusion — correct scope; no CPUcom.microsoft.FusedMatMulfor MLFloat16.- HalfGemm backend-selector plumbing cleanup — pruned trailing
MLAS_BACKEND_KERNEL_SELECTOR_CONFIG*fromMlasHalfGemmBatchOverrideand downstream stubs. - Value-initialization of MLAS data-params structs — zero-init
BiasandBackendKernelSelectorConfigpointers. - FP16 Gemm no-bias / beta==0 fast path — extends pre-existing fast path to the
beta == 0 with full-shape Ccase. - Both Copilot AI comments handled correctly — one accepted (
ORT_THROW_IF_ERROR→ASSERT_STATUS_NOT_OK_AND_HAS_SUBSTR), one correctly rebutted (input_defs[i]->Exists()is the canonical ORT pattern).
Test coverage across framework (BrokenKernelWithoutCacheableBuffersFails), MatMul (dynamic + shared-initializer), Gemm (no-C + beta==0), Conv (HalfConv-eligible NCHW/NHWC, with/without bias, KleidiAI-enabled/disabled fallback), and the fusion-exclusion (TransposeMatmulNoFusionForCpuFp16) is unchanged from pass-2 and remains thorough.
CI / merge state
- Head
385bdf1: 1 / 68 OK — brand new, still spinning up. - Approval history:
@hariharans29had approved3ef65e5earlier; auto-dismissed by the force-push. Currently zero approvals. - Both Copilot comments remain resolved on the force-pushed history.
- The three "Fix ... fallback / dispatch / tolerance" commits are the most direct evidence that a CI leg on the previous head surfaced a specific failure the author has now targeted. Whether the fix sticks will be clear once ARM64 / non-FP16-accel test legs report back — most likely candidates to watch:
- The Linux ARM64 CI leg (if it lands on a non-FEAT_FP16 machine): watch
MatMulFloat16*andGemm*_f16results. - The
TransposeMatmulNoFusionForCpuFp16andBrokenKernelWithoutCacheableBuffersFailsframework tests: unchanged from pass-2, should stay green.
- The Linux ARM64 CI leg (if it lands on a non-FEAT_FP16 machine): watch
Nits from prior passes still apply (all non-blocking)
data[i].BackendKernelSelectorConfigset redundantly per batch entry inMatMul<MLFloat16>::Compute. Matches the pattern forfloat, not worth refactoring here.- The three
has_accelerated_half_gemmprobe sites (MatMul / math::MatMul / Gemm) duplicate the same 4-line check. Refactoring into a helperbool MlasHalfGemmDispatchAvailable(N, K, config)would tighten it. Follow-up. PrePackedWeightsgains a public boolhas_kernel_owned_packed_weights_. Internal type; no C-API impact. Future PRs that serializePrePackedWeights(external-data path) will need to decide whether to include it in the manifest. Not this PR's problem.- In
gemm.cc,has_accelerated_half_gemmcomputed unconditionally even whenalpha != 1or transpose flags rule out MLAS. Minor wasted probe per call. Sub-noise.
Bottom line
The three new commits since pass-2 are targeted follow-ups to exactly the failure class I flagged as most likely to surface in CI (the runtime FP16 gate at the MatMul, math::MatMul, and Gemm_MLFloat16 fallback sites). Naming and scope suggest surgical fixes rather than architectural changes. The design substance from the pass-2 approval — has_kernel_owned_packed_weights_ marker, prepack-safety analysis, HalfGemm dispatch fix, MatmulTransposeFusion exclusion, backend-selector plumbing cleanup — is untouched.
Action items:
@JonathanC-ARM— nothing required beyond letting CI settle on385bdf1.@hariharans29— re-approval needed; the force-push auto-dismissed the earlier one. The pass-2 approval rationale (3ef65e5) all carries forward except the three new commits, which are described here.- Watch the ARM64 non-FEAT_FP16 CI legs first; that's where the pass-2 fixes were probing new dispatch behavior and where these three follow-up commits are aimed.
Ready to merge when CI reaches green on 385bdf1 and a Microsoft-side approver signs off.
Description
This PR builds on fp16-split/02-mlas-half-api-squashed by connecting its FP16 MLAS APIs and KleidiAI backends to the CPU Execution Provider.
Motivation and Context
This is pr 3 of 5 as per #28786 splitting suggestion
The preceding PR introduces the MLAS primitives for FP16 HalfGemm, backend-native B packing, and HalfConv, but standard ONNX CPU operators do not yet consume them.
This PR connects those primitives to CPU
MatMul,Gemm, andConv, making native FP16 execution and KleidiAI acceleration available to the operator layer while retaining portable fallback behavior for unsupported hardware, shapes, attributes, or backend configurations.The prepacking changes avoid repeatedly packing constant weights while preventing backend-specific or bias-dependent layouts from being incorrectly reused through the shared prepack cache.
This PR is limited to CPU kernel registration and execution. The follow-up InsertCastTransformer PR introduces the opt-in policy and shape heuristics that decide when graph optimization should preserve FP16 CPU nodes. Apple ARM64 build enablement is also handled separately.