Skip to content

[diskann-wide] Optimize load_simd_first for 8-bit and 16-bit element types. - #747

Merged
Mark Hildebrand (hildebrandmw) merged 3 commits into
mainfrom
mhildebr/epilogue
Feb 10, 2026
Merged

[diskann-wide] Optimize load_simd_first for 8-bit and 16-bit element types.#747
Mark Hildebrand (hildebrandmw) merged 3 commits into
mainfrom
mhildebr/epilogue

Conversation

@hildebrandmw

Copy link
Copy Markdown
Contributor

Optimize SIMDVector::load_simd_first for u8, i8 and u16 data type on the x86_64::V3 architecture.

These types use the __load_first* algorithms since AVX2 does not have masked loads for 8/16-bit types. The current implementation uses a cascaded load-chain to ensure the safety contract is upheld. This results in a lot of fiddly conditional logic.

This new implementation uses at most 2 data loads (plus sometimes one more load from a const variable for the shuffle-mask) to avoid the data dependent chain and avoids using the u128 type directly, which saves a bunch of LLVM register shenanigans.

These functions are called in the epilogue handling of many distance function implementations.

Performance results are below. This is a pretty clear win for the 8-bit case. It appears to be kind of a wash for the 16-bit case though.

uint8 x uint8 -- squared_l2
DimBefore Min (ns)After Min (ns)Delta Min
1006.5286.044-7.4%
1017.6606.052-21.0%
1027.7286.068-21.5%
1039.0006.084-32.4%
1045.8125.668-2.5%
1056.7246.024-10.4%
1286.2246.260+0.6%
1607.5447.532-0.2%
float16 x float16 -- squared_l2
DimBefore Min (ns)After Min (ns)Delta Min
1007.8167.548-3.4%
1018.0848.036-0.6%
1027.9168.032+1.5%
1038.0928.020-0.9%
1047.1287.316+2.6%
1058.8608.100-8.6%
1288.6848.632-0.6%
16010.69610.464-2.2%
float16 x float16 -- inner_product
DimBefore Min (ns)After Min (ns)Delta Min
1006.7566.480-4.1%
1016.9887.004+0.2%
1026.8046.968+2.4%
1036.9887.004+0.2%
1046.1406.112-0.5%
1057.4926.932-7.5%
1287.5567.564+0.1%
1609.4089.348-0.6%

CopilotAI 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.

Pull request overview

Optimizes partial SIMD loads on x86_64::V3 for u8/i8 and u16 element types by replacing the previous cascaded load-chain logic with overlapping-load strategies that preserve the “no out-of-bounds access” safety contract while improving throughput in distance-function epilogues.

Changes:

  • Added a new helper to efficiently load (8, 16) bytes using two 8-byte loads + pshufb (_mm_shuffle_epi8).
  • Reworked __load_first_of_16_bytes to use the new helper for first > 8 and overlapping GP-register reads for first <= 8.
  • Reworked __load_first_u16_of_16_bytes to use the new helper for bytes > 8 and GP-register reads for bytes <= 8, removing prior masked-load/insert logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hildebrandmw

Mark Hildebrand (hildebrandmw) commented Feb 10, 2026

Copy link
Copy Markdown
ContributorAuthor

The particular benchmark results can be run locally by using the following input to diskann-benchmark-simd.

JSON file
{
"search_directories": [],
"jobs": [
{
"type": "simd-op",
"content": {
"query_type": "uint8",
"data_type": "uint8",
"arch": "x86-64-v3",
"runs": [
{
"distance": "squared_l2",
"dim": 100,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 101,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 102,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 103,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 104,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 105,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 128,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 160,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
}
]
}
},
{
"type": "simd-op",
"content": {
"query_type": "float16",
"data_type": "float16",
"arch": "x86-64-v3",
"runs": [
{
"distance": "squared_l2",
"dim": 100,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 101,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 102,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 103,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 104,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 105,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 128,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "squared_l2",
"dim": 160,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 100,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 101,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 102,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 103,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 104,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 105,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 128,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
},
{
"distance": "inner_product",
"dim": 160,
"num_points": 50,
"loops_per_measurement": 5000,
"num_measurements": 100
}
]
}
}
]
}

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Feb 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.00%. Comparing base (a7aa13c) to head (3ce5d4c).

Additional details and impacted files

Impacted file tree graph

@@ Coverage Diff @@## main #747 +/- ##
==========================================
- Coverage 89.01% 89.00% -0.01% 
==========================================
Files 428 428 Lines 78294 78295 +1 ==========================================
- Hits 69691 69687 -4 - Misses 8603 8608 +5 
FlagCoverage Δ
miri89.00% <100.00%> (-0.01%)⬇️
unittests89.00% <100.00%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
diskann-wide/src/arch/x86_64/algorithms.rs100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

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

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.

LGTM, cool trick with the _load_8_to_16_bytes logic.

Comment threaddiskann-wide/src/arch/x86_64/algorithms.rs
@hildebrandmw
Mark Hildebrand (hildebrandmw) merged commit e873811 into mainFeb 10, 2026
26 checks passed
@hildebrandmw
Mark Hildebrand (hildebrandmw) deleted the mhildebr/epilogue branch February 10, 2026 19:27
Mark Hildebrand (hildebrandmw) added a commit that referenced this pull request Feb 13, 2026
## What's Changed
### API Breaking Changes
* Remove the `experimental_avx512` feature. by @hildebrandmw in
#732
* Use VirtualStorageProvider::new_overlay(test_data_root()) in tests by
@Copilot in #726
* save and load max_record_size and leaf_page_size for bftrees by
@backurs in #724
* [multi-vector] Verify `Standard` won't overflow in its constructor. by
@hildebrandmw in #757
* VirtualStorageProvider: Make new() private, add new_physical by
@Copilot in #764
* [minmax] Refactor full query by @arkrishn94 in
#770
* Bump diskann-quantization to edition 2024. by @hildebrandmw in
#772
### Additions
* [multi-vector] Enable cloning of `Mat` and friends. by @hildebrandmw
in #759
* adding bftreepaths in mod.rs by @backurs in
#775
* [quantization] Add `as_raw_ptr`. by @hildebrandmw in
#774
### Bug Fixes
* Fix `diskann` compilation without default-features and add CI tests.
by @hildebrandmw in #722
### Docs and Comments
* Updating the benchmark README to use diskann-benchmark by @bryantower
in #709
* Fix doc comment: Windows line endings are \r\n not \n\r by @Copilot in
#717
* Fix spelling errors in streaming API documentation by @Copilot in
#715
* Add performance diagnostic to `diskann-benchmark` by @hildebrandmw in
#744
* Add agents.md onboarding guide for coding agents by @Copilot in
#765
* [doc] Fix lots of little typos in `diskann-wide` by @hildebrandmw in
#771
### Performance
* [diskann-wide] Optimize `load_simd_first` for 8-bit and 16-bit element
types. by @hildebrandmw in #747
### Dependencies
* Bump bytes from 1.11.0 to 1.11.1 by @dependabot[bot] in
#723
* [diskann] Add note on the selection of `PruneKind` in
`graph::config::Builder`. by @hildebrandmw in
#734
* [diskann-providers] Remove the LRU dependency and make `vfs` and
`serde_json` optional. by @hildebrandmw in
#733
### Infrastructure
* Add initial QEMU tests for `diskann-wide`. by @hildebrandmw in
#719
* [CI] Skip coverage for Dependabot. by @hildebrandmw in
#725
* Add miri test coverage to CI workflow by @Copilot in
#729
* [CI] Add minimal ARM checks by @hildebrandmw in
#745
* Enable CodeQL security analysis by @Copilot in
#754
## New Contributors
* @backurs made their first contribution in
#724
* @arkrishn94 made their first contribution in
#770
**Full Changelog**:
0.45.0...0.46.0
Sign up for freeto 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.

5 participants

@hildebrandmw@codecov-commenter@harsha-simhadri@arkrishn94