Releases: microsoft/DiskANN
DiskANN v0.54.0
Breaking changes since 0.53.0
Graph search: DataProvider contract collapsed into SearchAccessor (#1067)
Accessor, BuildQueryComputer, ExpandBeam, SearchExt, and AsNeighbor/NeighborAccessor are merged into a single SearchAccessor trait. The indexing layer no longer has a notion of element types.
- Upgrade: Implement
SearchAccessorinstead of the removed traits; useSearchAccessor::expand_beamfor search.SearchStrategy/InsertStrategy/DefaultSearchStrategy/DefaultPostProcessornow carry a lifetime, and the query is passed intosearch_accessor(accessors may now borrow the query).SearchPostProcessno longer takes aQueryComputer(only requiresHasId). The blanketworkingset::Fillimpl forworkingset::Mapwas removed — implementFillyourself, or use the new synchronousMap::fillhelper.
Insert/prune: consolidated into PruneAccessor (#1138, follow-up to #1067)
Removed DelegateNeighbor, AsNeighbor, AsNeighborMut, HasElementRef, BuildDistanceComputer, workingset::Fill, and workingset::AsWorkingSet, folded into a single PruneAccessor trait.
- Upgrade: Implement
PruneAccessor(providesneighbors()for neighbor delegation andfill()returning both aViewand the distance computer). Noteneighbors()now borrows&mut self.
VectorId: removed scalar conversion traits/bounds (#1145, #1133)
Dropped VectorIdTryFrom, TryIntoVectorId, methods vector_id_try_from/try_into_vector_id, helpers vecid_from_u32/vecid_from_usize, and IdConversionError/ErrorToVectorId. Internal IDs no longer need to convert to/from usize.
- Upgrade: Where
usizeconversion is still required (e.g. roaring-treemap keys indiskann-label-filter), add an explicitIntoUsizebound (now required onRoaringAttributeStore,InlineBetaStrategy,QueryBitmapEvaluator/BitmapFilter).DiskANNIndex::prune_rangenow takesimpl IntoIterator<Item = DP::InternalId> + Sendinstead ofRange<DP::InternalId>— construct the iterator for your ID type at the call site.SimpleNeighborProviderAsyncandbftree::VectorProviderare no longer generic over the ID type (fixed tou32).
DiskIndexReader: dropped vestigial VectorType generic (#1161)
- Upgrade: Replace
DiskIndexReader::<T>::new(...)withDiskIndexReader::new(...).
Filtered search renames (#1149)
MultihopSearch → MultihopFilterSearch; benchmark config phases MultiHopSearchPhase/InlineSearchPhase → MultihopFilterSearchPhase/InlineFilterSearchPhase.
- Upgrade: Update references to the new names.
diskann-garnet FFI: BIN/Q8 quantizers, bumped to 2.0.0 (#1050)
Vectors are now stored as Poly<[u8], AlignOfEight>; a type-erased GarnetQuantizer trait replaces index/provider type parameterization. New FFI: insert() returns a success/training-ready flag, plus build_quant_table() and backfill_quant_vectors() for caller-driven async training/backfill. Accessor renamed to DynamicAccessor; the FSM is now lockable and gained visit_used().
- Upgrade: Garnet consumers must adopt the new 2.0.0 FFI surface (handle the new
insert()return flag and drivebuild_quant_table/backfill_quant_vectors).
Full list of changes.
- Multi-vector MaxSim benchmark with BYOTE factory by @suri-kumkaran in #1027
- BufferedFnPtr and take
UnalignedSlice. by @hildebrandmw in #1113 - [diskann-wide] Test unaligned loads properly. by @hildebrandmw in #1110
- [diskann-garnet] Implement BIN and Q8 quantizers by @metajack in #1050
- Right-size tile conversion buffer in
tiled_reduceby @suri-kumkaran in #1123 - Add JobId labels to disk benchmark CI runners by @arrayka in #1120
- nightly: remove stale
bf_treefeature from DISKANN_FEATURES by @Copilot in #1112 - Add a small streaming runbook and groundtruth to test_data by @magdalendobson in #1127
- fix: redirect disk-index benchmark build artifacts to target/tmp by @arrayka in #1132
- Remove
try_into_vector_idconversion in prune. by @hildebrandmw in #1133 - [diskann-garnet] Fix handling of missing quant vectors during delete() by @metajack in #1130
- Simplify the
DataProvidercontract for graph search by @hildebrandmw in #1067 - Add Documentation DO/DON'T section in
agents.mdby @suri-kumkaran in #1103 - Fix quantizer detection in train_quantizer() and set_element() by @metajack in #1140
- add bf_tree benchmark infrastructure by @JordanMaples in #1106
- [RFC] What filtered search algorithms should DiskANN support? by @magdalendobson in #1128
- Inline filtered search with adaptive L by @magdalendobson in #1131
- [benchmark] Spherical exhaustive benchmark threadpool bug by @arkrishn94 in #1148
- Consolidate insert into
PruneAccessorby @hildebrandmw in #1138 - Rename MultihopSearch to MultihopFilterSearch by @magdalendobson in #1149
- [bftree] Bug with writing length to neighbor list by @arkrishn94 in #1150
- Fix handling of deletes and ID minting during concurrent insert/delete by @metajack in #1146
- [VectorId] Remove Id conversion bounds and traits by @arkrishn94 in #1145
- Remove vestigial VectorType parameter from DiskIndexReader by @doliawu in #1161
- change documentation link to repository link by @harsha-simhadri in #1156
- [diskann-garnet] Fix handling of start points on fresh indexes by @metajack in #1167
- Bump version to 0.54.0 by @arkrishn94 in #1165
Full Changelog: v0.53.0...v0.54.0
diskann-garnet v2.0.4
Fixed handling of start points on fresh indexes.
diskann-garnet v2.0.3
Fixed race condition where IDs could be handed out multiple times.
diskann-garnet v2.0.2
Fixed issue where quantizer training could be retriggered.
diskann-garnet 2.0.1
Small bugfix release. Fixes handling of missing quant vectors during delete().
diskann-garnet v2.0.0
This release adds support for I8 vectors as well as binary (BIN) and scalar 8-bit (Q8) quantizers. For f32 vectors, the available quantizers are now NOQUANT, BIN, and Q8. For u8 and i8 vectors, XNOQUANT_U8, XNOQUANT_I8, XBIN_U8, and XBIN_I8 are available.
The version is now 2.0.0 to account for the FFI changes.
Note, quantization support is not yet persisted to disk, so this release should be used for in-memory workloads only. Persistence will follow shortly.
DiskANN v0.53.0
DiskANN v0.53.0 Release Notes
Breaking Changes
An AI generated, human reviewed list of changes is summarized below.
Paged search overhauled — channel-based API (#1078)
PagedSearchState and its 'static-bound pause/resume model have been replaced with an async, channel-based interface. The recommended way to drive paged search is now via a tokio::sync::mpsc channel, with the searcher embedded in an otherwise-'static future. See the rendered RFC for the new shape. Callers wired against PagedSearchState must migrate to the channel API.
Users of paged search via wrapped_async::DiskANNIndex that know their inner futures will never suspend can use the new wrapped_async::DiskANNIndex::paged_search_no_await; this will efficiently run paged searches with minimal synchronization overhead.
DiskANNIndex::flat_search removed (#1076)
DiskANNIndex::flat_search and the IdIterator trait have been removed from the diskann crate. Equivalent functionality lives on the new inherent method DiskIndexSearcher::flat_search in diskann-disk. This unblocks the experimental directions in #1067 and #983.
// Before
diskann_index.flat_search(query, ...)?;
// After
disk_index_searcher.flat_search(query, ...).await?;DiskIndexSearcher::flat_search now batched (#1097)
The new DiskIndexSearcher::flat_search uses the bulk pq_distances path instead of one-vector-at-a-time Accessor::build_query_computer + evaluate_similarity. Downstream behavior is equivalent but tighter resource bounds apply.
centroid removed from PQ interfaces (#1010)
The dataset-centroid argument has been removed from FixedChunkPQTable construction, populate, and most other PQ APIs. The shift only ever worked for L2 distance and was silently ignored for inner-product / cosine, so passing it was a footgun. When an L2 shift is required, fold it into the PQ pivots instead (the library now does this internally).
// Before
let table = FixedChunkPQTable::new(.., centroid, ..);
// After — drop the centroid argument
let table = FixedChunkPQTable::new(.., ..);Flat search interface (#983)
A new flat module in diskann adds a provider-agnostic brute-force search surface, mirroring the shape of graph search. Backends implement a single trait, DistancesUnordered<C> (in flat/strategy.rs), which fuses iteration and distance computation, allowing any backend (in-memory, quantized, disk, remote) to plug into a shared algorithm. See the rendered RFC. This is additive but is the new canonical surface — direct ad-hoc flat-search call sites should migrate.
bf_tree extracted into diskann-bftree crate (#1020)
The bf_tree provider has been moved out of diskann-providers (previously at diskann-providers/src/model/graph/provider/async_/bf_tree/) into a new standalone diskann-bftree crate. Along with the move:
- Switched from PQ to spherical quantization.
- Dropped dependencies on
DeletionCheck,AsDeletionCheck, andRemoveDeletedIdsAndCopy. - Simplified generics.
Consumers must update their Cargo.toml to depend on diskann-bftree and update import paths.
direct_distance_impl and inner_product_raw re-exposed (#1081)
direct_distance_impl (free function) and FixedChunkPQTable::inner_product_raw are pub again after being privatized in #1044. Restored to unblock a downstream user. Not breaking in the typical direction — this restores previously available API surface.
MinMax recompress takes a grid-scale parameter (#1109)
The MinMax recompress API now accepts a grid-scale parameter.
New Features
- SIMD-optimized L2-squared norm (#1107)
- Significantly faster bitmap computation (#1099)
- Large speedup on the bitmap construction path used by filtered search.
- LLVM IR bloat regression check in CI (#1083)
- CI now flags regressions in generated LLVM IR size, helping catch unintended monomorphization blow-ups.
- Recall computation fix for under-k groundtruth (#1069)
Full List of Changes
- [CI] Try to fix publishing step by @hildebrandmw in #1057
- Revise README for DiskANN3 by @harsha-simhadri in #1046
- [benchmark] Remove
DispatchRuleby @hildebrandmw in #1064 - [benchmark] Automatic Input Registration by @hildebrandmw in #1066
- Remove centroid from most PQ interfaces. by @hildebrandmw in #1010
- [diskann/disk] Remove
flat_searchfromDiskANNIndexby @hildebrandmw in #1076 - macos build and miri check to nightly by @harsha-simhadri in #1058
- [API] Make some methods public again. by @hildebrandmw in #1081
- [benchmark] Simply
Inputsmore. by @hildebrandmw in #1077 - Turn on stack protection for the diskann-garnet NuGet build by @metajack in #1082
- Fix options for diskann-garnet nuget pipeline by @metajack in #1091
- [CI] add LLVM IR bloat regression check by @arrayka in #1083
- Bump openssl from 0.10.79 to 0.10.80 by @dependabot[bot] in #1093
- [Disk CI benchmarks] Use 1ES.Pool=diskann-github by @arrayka in #869
- Fix recall computation for fewer than k groundtruth results by @magdalendobson in #1069
- bf_tree migration away from diskann-providers by @JordanMaples in #1020
- [RFC/diskann] Overhaul paged search by @hildebrandmw in #1078
- Remove unsafe code from compute_vec_l2sq by @arrayka in #1094
- Remove direct accessor call in
diskann-garnetby @hildebrandmw in #1098 - Refactor
DiskIndexSearcher::flat_searchto use batching by @hildebrandmw in #1097 - [flat index] Flat Search Interface by @arkrishn94 in #983
- migrating multi-hop tests from diskann-providers to diskann by @JordanMaples in #928
- Significantly speed up bitmap computation by @magdalendobson in #1099
- compute_vecs_l2sq: Replace scalar L2 Squared norm with SIMD-optimized FastL2NormSquared by @arrayka in #1107
- [minmax] Add grid scaling to recompress API by @arkrishn94 in #1109
- Bump version to 0.53.0 by @arkrishn94 in #1111
New Contributors
- @magdalendobson made their first contribution in #1069
Full Changelog: v0.52.0...v0.53.0
diskann-garnet v1.0.27
This release adds stack protectors to the diskann-garnet library.
DiskANN v0.52.0
DiskANN v0.52.0 Release Notes
Breaking Changes
An AI generated, human reviewed list of changes is summarized below.
get_degree_stats signature changed (#998)
DiskANNIndex::get_degree_stats now takes an explicit iterator of IDs instead of requiring the data provider to implement IntoIterator.
// Before — provider had to impl IntoIterator
index.get_degree_stats(&mut accessor)?;
// After — caller supplies the ID iterator
index.get_degree_stats(&mut accessor, id_iter)?;PQ dimension contract tightened; entries now &[f32] only (#1044)
With AlignedBoxWithSlice removed from the PQ path, the dimension handling has been refactored into a three-layer contract:
| Layer | Where | Contract |
|---|---|---|
| Boundary (inmem) | QueryComputer::new, MultiQueryComputer::new, DistanceComputer::evaluate_similarity |
len == dim (returns Err on mismatch) |
| Boundary (disk) | PQScratch::set |
len >= dim, slices to [..dim] |
| Internal | TableL2/IP/Cosine::{new, populate} |
Trusted — no re-validation |
Other changes:
- PQ table populate/distance methods now accept
&[f32]instead of<U: Into<f32>>. Callers must pre-decode quantized vectors viaVectorRepr::as_f32. - Generic trampoline impls (
&Vec<u8>,&&[u8]) onQueryComputer/DistanceComputerhave been removed.
calculate_chunk_offsets relocated to ChunkOffsets constructors (#976)
The free functions calculate_chunk_offsets and calculate_chunk_offsets_auto have been moved into constructors on ChunkOffsets / ChunkOffsetsView in diskann-quantization::views.
// Before
let offsets = calculate_chunk_offsets(dim, num_chunks);
// After (allocating)
let offsets = ChunkOffsets::partition(dim, num_chunks)?;
// After (zero-alloc, borrows caller-owned scratch)
let view = ChunkOffsetsView::partition_into(dim, &mut scratch)?;Additionally, get_chunk_from_training_data has been moved from public API.
CachingProvider removed (#1052)
The entire diskann_providers::model::graph::provider::async_::caching module has been deleted.
Why: The CachingProvider was an experiment in transparent caching over DataProvider. In practice it required double monomorphization of the indexing code, didn't save integration work for bulk methods like on_elements_unordered/distances_unordered, and was complex to maintain. An internal user who …migrated off it removed ~1,000 lines of code, improved compile times by ~20%, and substantially reduced complexity.
Upgrade: Manage caching directly in your DataProvider implementation.
New Features
AVX-512 4-bit distance kernels (#1045)
Native V4 (AVX-512) specializations for 4-bit packed vector distance computations:
SquaredL2— 16 ×u32lanes per iteration via_mm512_madd_epi16.InnerProduct— AVX-512 VNNI (_mm512_dpbusd_epi32) overu8x64/i8x64operands.
Previously, V4 hardware fell back to two AVX2 (V3) kernel invocations per 512-bit chunk. The native kernels double per-instruction throughput. No API changes — existing code benefits automatically on AVX-512 capable hardware.
Merged PRs
- Deprecate 32-bit targets by @suhasjs in #1022
- Add a fast path to
Map::prepare. by @hildebrandmw in #1023 - Add boundary checks in gen_associated_data_from_range() by @Copilot in #847
- [deps] Don't pull
rayonas a dependency ofdiskann. by @hildebrandmw in #1024 - Bump openssl from 0.10.78 to 0.10.79 by @dependabot[bot] in #1026
- Cleaning up test work and changing the get_degree_stats signature. by @JordanMaples in #998
- Reduce scalar-quantization benchmark monomorphization by @suri-kumkaran in #1041
- [diskann-vector] Support truly unaligned distances. by @hildebrandmw in #981
- rename spherical.json to graph index with spherical quantization by @harsha-simhadri in #1042
- [PQ Cleanup] Part 2: Consolidate
calculate_chunk_offsets*by @arkrishn94 in #976 - PQ: tighten dim contract; right-size scratch buffer by @wuw92 in #1044
- Add v4 distance kernels (4-bit SquaredL2 / InnerProduct) by @m3hm3t in #1045
- Remove the Caching Provider by @hildebrandmw in #1052
New Contributors
Full Changelog: v0.51.0...v0.52.0
DiskANN v0.51.0
What's Changed
- Bump openssl from 0.10.75 to 0.10.78 by @dependabot[bot] in #973
- Move ObjectPool from diskann to diskann-utils by @arkrishn94 in #975
- remove alignedslice and replace with direct poly calls by @JordanMaples in #994
- compute_closest_centers(): remove unnecessary allocation when pts_norms_squared is provided by @arrayka in #980
- [diskann-disk] Decouple buffer memory alignment from disk block_size by @doliawu in #984
- Add A/A benchmark documentation by @YuanyuanTian-hh in #974
- [benchmark/filtered-search prep] Make benchmarks stateful by @hildebrandmw in #995
- Remove AsThreadPool generic and take &RayonThreadPool directly by @JordanMaples in #967
- Cache-Aware Block-Transposed Chamfer/MaxSim Distance for f32 and f16 by @suri-kumkaran in #863
- crate publishing workflow by @Copilot in #755
- Rename async to graph-index in diskann-benchmark by @harsha-simhadri in #1009
- Relax the
'staticbound onDistanceComputer. by @hildebrandmw in #1007 - Remove unnecessary distance function implementations. by @hildebrandmw in #1008
- Replace sgemm() panics with Result-based error handling by @arrayka in #997
- [benchmark/filtered-search prep] Search Plugins by @hildebrandmw in #996
- [CI] Fix publish dry-run check to skip non-publishable crates by @arkrishn94 in #1017
- [v0.51.0] Bump version to 0.51.0 by @arkrishn94 in #1013
Full Changelog: v0.50.1...v0.51.0