Skip to content

[diskann-vector] Optimise AArch64 FP16 Inner Products using FMLAL - #1500

Merged
Mark Hildebrand (hildebrandmw) merged 6 commits into
microsoft:mainfrom
UtsavGoelArm:UtsavGoelArm/ip_f16_fmlal
Nov 3, 2026
Merged

Mark Hildebrand (hildebrandmw) merged 6 commits into
microsoft:mainfrom
UtsavGoelArm:UtsavGoelArm/ip_f16_fmlal

Conversation

@UtsavGoelArm

Copy link
Copy Markdown
Contributor
  • Does this PR have a descriptive title that could go in our release notes?
  • Does this PR add any new dependencies? Yes, new CPU feature flag requirement for Arm.
  • Does this PR modify any existing APIs?
  • Is the change to the API backwards compatible?
  • Should this result in any changes to our documentation, either updating existing docs or adding new ones?

What does this implement/fix? Briefly explain your changes.

This PR optimises the AArch64 half-precision inner-product kernel using FMLAL (vector). It replaces explicit FP16-to-FP32 conversions followed by FP32 fused multiply-add with a single instruction.

FMLAL is implemented using inline assembly in SIMDDotProduct<f16x4> for f32x4, which supports FP16 inputs with FP32 accumulation, unlike SIMDMulAdd.

Any other comments?

FMLAL requires FHM (floating-point half-precision multiplication instructions), which the target configuration explicitly enables alongside the already configured DotProd feature. FHM is mandatory from Armv9.0 when floating-point and Advanced SIMD are implemented. See Arm’s architecture requirements. It is therefore safe to assume that this is available on C100 and C200.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new CPU requirement breaks Graviton 2 compatibility and leaves the cross-compilation helper skipping Neon tests by default.

2 open issues
What changed in this PR

This PR accelerates DiskANN’s AArch64 FP16 inner products using FMLAL with FP32 accumulation.

Changes:

  • Adds an FMLAL-backed SIMD operation and unit test.
  • Uses it in the FP16 inner-product kernel.
  • Adds FHM to the Neon backend requirements and default build flags.
File Description
diskann-wide/​src/​arch/​aarch64/​mod.rs Requires FHM for Neon selection.
diskann-wide/​src/​arch/​aarch64/​f32x4_.rs Implements and tests FP16 FMLAL accumulation.
diskann-vector/​src/​distance/​simd.rs Uses the new operation for inner products.
.cargo/​config.toml Enables FHM for AArch64 builds.

Review effort: Balanced

Comment thread .cargo/config.toml Resolved
Comment thread diskann-wide/src/arch/aarch64/mod.rs Resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I generally support this feature, even though it slightly raises the minimum hardware requirement for Neon support. I think the CPUs that don't support FHM are all from like 2019 and 2020 - so while still available, there are plenty more CPUs that support this instruction.

Comment thread .cargo/config.toml Resolved
Comment thread diskann-wide/src/arch/aarch64/f32x4_.rs Resolved
Comment thread diskann-wide/src/arch/aarch64/f32x4_.rs Resolved
@UtsavGoelArm

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree company="Arm"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small request - otherwise looks good!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 40.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.05%. Comparing base (2739203) to head (816fbe9).
⚠️ Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
diskann-wide/src/test_utils/dot_product.rs 40.00% 3 Missing ⚠️

❌ Your patch status has failed because the patch coverage (40.00%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1500      +/-   ##
==========================================
- Coverage   92.07%   92.05%   -0.03%     
==========================================
  Files         586      605      +19     
  Lines      119997   125510    +5513     
==========================================
+ Hits       110488   115532    +5044     
- Misses       9509     9978     +469     
Flag Coverage Δ
miri 92.05% <40.00%> (-0.03%) ⬇️
unittests 91.99% <40.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
diskann-vector/src/distance/simd.rs 91.06% <ø> (ø)
diskann-wide/src/test_utils/dot_product.rs 98.26% <40.00%> (-1.30%) ⬇️

... and 100 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@UtsavGoelArm

Copy link
Copy Markdown
Contributor Author

Mark Hildebrand (@hildebrandmw) Codecov seems to flag the new FP16 ExpectedDot implementation, even though we use test_dot_product! for f16x4. Is this coverage worth addressing? Perhaps we could add a something like:

#[test]
fn test_f16_f16_to_f32_expected_dot() {
    let acc = 0.25;
    let left = [f16::from_f32(1.5)];
    let right = [f16::from_f32(-2.0)];

    assert_eq!(<DotSchema as ExpectedDot<f32, f16, f16, 1>>::expected_dot(acc, &left, &right), -2.75);
}

@hildebrandmw

Copy link
Copy Markdown
Contributor

Mark Hildebrand (Mark Hildebrand (@hildebrandmw)) Codecov seems to flag the new FP16 ExpectedDot implementation, even though we use test_dot_product! for f16x4. Is this coverage worth addressing? Perhaps we could add a something like:

#[test]
fn test_f16_f16_to_f32_expected_dot() {
    let acc = 0.25;
    let left = [f16::from_f32(1.5)];
    let right = [f16::from_f32(-2.0)];

    assert_eq!(<DotSchema as ExpectedDot<f32, f16, f16, 1>>::expected_dot(acc, &left, &right), -2.75);
}

Coverage is not yet worth addressing. Our CI runner only runs on x86, so Arm code is inherently going to get flagged by low coverage. That's on us, not you 😄.

@hildebrandmw
Mark Hildebrand (hildebrandmw) merged commit d6ef533 into microsoft:main Nov 3, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants