KFI-543 Integrate SME2 kernels matmul_clamp_f16_qai8dxp_qsi8cxp#10686
KFI-543 Integrate SME2 kernels matmul_clamp_f16_qai8dxp_qsi8cxp#10686Colm-in-Arm wants to merge 3 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Added: * kai_matmul_clamp_f16_qai8dxp1vlx4_qsi8cxp4vlx4_1vlx4vl_sme2_mopa * kai_matmul_clamp_f16_qai8dxp1x4_qsi8cxp4vlx4_1x4vl_sme2_dot Signed-off-by: Colm Donelan <colm.donelan@arm.com>
a261f90 to
db663bb
Compare
Signed-off-by: Colm Donelan <colm.donelan@arm.com>
| // (XNN_ARCH_ARM64 && __ARM_FEATURE_FMA && | ||
| // defined(__ARM_FEATURE_FP16_FML)) | ||
| #else | ||
| // Computing f16 fused ops via float rounds once at the final f16 conversion. |
There was a problem hiding this comment.
This doesn't seem right. computing fp16 fma with floats would do a double rounding, wouldn't it?
(Interestingly, doing fp16 fma with fp64 does avoid double rounding, because the mantissa is big enough to hold any intermediate sum. But we don't do fma with fp64.)
There was a problem hiding this comment.
This was quite the rabbit hole when I first encountered it. It started with these two test failures on M4:
[ RUN ] F16SimdSCALARTest.Fmsub
test/simd/f16-simd-scalar.cc:132: Failure
Expected equality of these values:
output_f32[k]
Which is: 46.4375
TruncToF16(inputs_f32[k] * inputs_f32[k + 1] - inputs_f32[k + 2 * 1])
Which is: 46.46875
Google Test trace:
./test/replicable_random_device.h:92: To replicate this failure, re-run the test with --gtest_random_seed=36814.
[ FAILED ] F16SimdSCALARTest.Fmsub (0 ms)
[ RUN ] F16SimdSCALARTest.Fnmadd
test/simd/f16-simd-scalar.cc:156: Failure
Expected equality of these values:
output_f32[k]
Which is: -46.4375
TruncToF16(-inputs_f32[k] * inputs_f32[k + 1] + inputs_f32[k + 2 * 1])
Which is: -46.46875
Google Test trace:
./test/replicable_random_device.h:92: To replicate this failure, re-run the test with --gtest_random_seed=36814.
When I added some printouts all fingers pointed to double rounding and setting XNN_SIMD_HAS_NATIVE_FMA reliably solved the problem. However, when I look at it again today, things aren't quite so clear. Rolling back this change makes this failure quite intermittent 9/20 runs of it will fail on M4. I'll continue to investigate.
There was a problem hiding this comment.
I believe I’ve found the root cause of these test failures.
The code above determines whether native FMA is available for the compilation target, and the tests use XNN_SIMD_HAS_NATIVE_FMA to decide whether to expect fused results. However, the workspace .bazelrc specifies --copt='-ffp-contract=off'. With that option, the compiler is not allowed to contract ordinary multiply/add expressions into FMA instructions, even if the target hardware supports FMA.
That means the implementation can legally compute the multiply and add/subtract as separate operations, while the test expects single-rounding fused behavior if it has determined the hardware supports it. For some random seeds this exposes a double-rounding difference, which explains the intermittent failures.
I’ll revert the change above. The follow-up question is whether the F16/F32 SIMD tests should be changed so that fused expectations are only used for implementations that explicitly perform FMA, rather than simply when the target has native FMA support.
* Reverting an earlier change to src/xnnpack/simd/f16-scalar.h as it appears to be as a result of CI artifact. * Fixing an assert format in qp8-f16-qc8w-gemm-minmax-16x64c4-neonsme2.c Signed-off-by: Colm Donelan <colm.donelan@arm.com>
This change integrates the aarch64 SME2 matmul_clamp_f16_qai8dxp_qsi8cxp path for FP16-output dynamically quantized fully connected workloads with QC8 weights. It enables packed-QP8 LHS execution where the graph and source datatype match the kernel contract.
KleidiAi kernels integrated
Specific changes to note
src/operator-run.c
Updates QP8 GEMM output column stride handling to use the operator’s configured output element size instead of assuming sizeof(float). This is needed because QP8 kernels can now produce either FP32 or FP16 outputs.
src/subgraph.c
Extends packed-LHS optimization for qdint8 -> fp16 fully connected nodes with QC8 weights to select the qp8_f16_qc8w path when the original pre-quantized input is FP16. The rewrite is gated on the convert source datatype so FP32 sources remain on the existing QD8 path.
src/xnnpack/simd/f16-scalar.h
Corrects the scalar FP16 SIMD FMA capability flag. Plain scalar _Float16 expressions do not explicitly perform fused operations, so the scalar backend reports non-fused rounding semantics when native FP16 is available.