Skip to content

Unified index format V1#1221

Open
Sanhaoji2 wants to merge 6 commits into
jegao/LabelHotFixfrom
jegao/UnifyIndexFormat
Open

Unified index format V1#1221
Sanhaoji2 wants to merge 6 commits into
jegao/LabelHotFixfrom
jegao/UnifyIndexFormat

Conversation

@Sanhaoji2

Copy link
Copy Markdown
Contributor

Add a single-file unified index container (docs/unified_index_format.md) that can be built once and loaded as either an in-memory or SSD-served index:

  • New class hierarchy: unified_index (interface) + unified_index_base with unified_index_memory / unified_index_ssd, backed by unified_node_store and unified_label_data (bitmask + integer encodings).
  • UnifiedIndexWriter/Reader (unified_index_io) and unified_index_builder for end-to-end build with optional PQ.
  • Index::save_unified emits the container; get_table_stats() exposed on the unified index (mirrors Index/PQFlashIndex).
  • Build the unit tests against a new static diskann_s lib (DISKANN_STATIC_LIB) so internal symbols need not be exported from the DLL.
  • Tests: node-store/label/factory/memory/ssd/builder suites plus legacy<->unified parity (memory, SSD, filtered) and get_table_stats coverage.
  • Fix: populate _label_map during filtered build so save_unified after build emits a valid label dictionary.
  • Does this PR have a descriptive title that could go in our release notes?
  • Does this PR add any new dependencies?
  • 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?

Reference Issues/PRs

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

Any other comments?

Add a single-file unified index container (docs/unified_index_format.md) that
can be built once and loaded as either an in-memory or SSD-served index:

- New class hierarchy: unified_index (interface) + unified_index_base<T> with
  unified_index_memory<T> / unified_index_ssd<T>, backed by unified_node_store
  and unified_label_data (bitmask + integer encodings).
- UnifiedIndexWriter/Reader (unified_index_io) and unified_index_builder for
  end-to-end build with optional PQ.
- Index::save_unified emits the container; get_table_stats() exposed on the
  unified index (mirrors Index/PQFlashIndex).
- Build the unit tests against a new static diskann_s lib (DISKANN_STATIC_LIB)
  so internal symbols need not be exported from the DLL.
- Tests: node-store/label/factory/memory/ssd/builder suites plus legacy<->unified
  parity (memory, SSD, filtered) and get_table_stats coverage.
- Fix: populate _label_map during filtered build so save_unified after build
  emits a valid label dictionary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hildebrandmw hildebrandmw added the C++ Pull Request targeting C++ label Jul 2, 2026
throw ANNException("unified_node_store_base: offset table size mismatch", -1, __FUNCSIG__, __FILE__,
__LINE__);
}
_coord_bytes = _header.aligned_dim * sizeof(T);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

keep consistency with write corrd_bytes

Comment thread src/index.cpp
static_cast<uint64_t>(_start));

writer.begin_graph_region();
std::vector<T> vec(dim);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

dim ? aligned_dim? keep consistency write/read

Sanhaoji2 and others added 5 commits July 6, 2026 11:48
UnifiedIndexWriter::write_node wrote coords as dim*sizeof(T), but the node
store decodes them as aligned_dim*sizeof(T) (and the distance functions read
the full aligned width). When dim is not a multiple of 8 (e.g. 66 -> 72) the
offset math desynced: wrong derived degree, neighbor pointer landing inside
the coord region, and distances reading neighbor bytes as coords.

- write_node now zero-pads coords from dim to aligned_dim so writer and reader
  agree on the per-node stride (keeps the aligned-SIMD distance path).
- docs/unified_index_format.md: coords documented as aligned_dim*sizeof(T)
  (padded from dim); degree-derivation formula updated.
- Add parity_unaligned_dim_66 regression test (dim=66): memory + SSD unified
  search now match legacy exactly (50/50); pre-fix it was 39/50 and 38/50.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add DISKANN_DLLEXPORT to the unified_index_builder class so its single public
build() entry point can be called across the DLL boundary (e.g. from the AdsSnr
PublicDiskANNBuilderWrapper). Other unified_* classes remain unexported (internal
to the DLL / static lib).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add DISKANN_DLLEXPORT to make_unified_index_memory and make_unified_index_ssd so
the unified index can be loaded/searched across the DLL boundary (e.g. from the
AdsSnr PublicDiskANNWrapper serving side).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
simple_bitmask was 'class DISKANN_DLLEXPORT', but consumers that compile
label_bitmask.cpp directly (e.g. AdsSnr's ANNTestTool, which defines neither
_WINDLL nor DISKANN_STATIC_LIB) then define its members in a dllimport context,
triggering C4273 'inconsistent dll linkage' (a build error under CloudBuild
warning-as-error/auto-baseline).

Make all simple_bitmask methods inline (header-only) and remove the class-level
DISKANN_DLLEXPORT; label_bitmask.cpp now has no out-of-line definitions. This
resolves the odr-use from ColorInfoVector's inline constructor (color_info.h)
locally in every consumer -- DLL, static lib, and direct-compile -- with no
import/export, eliminating C4273.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Supersedes the header-only inlining (304457a) with the minimal change: remove
DISKANN_DLLEXPORT from simple_bitmask and restore label_bitmask.cpp to its original
out-of-line definitions. This is sufficient to fix the C4273 'inconsistent dll
linkage' in projects that compile label_bitmask.cpp directly (e.g. ANNTestTool);
every module that odr-uses simple_bitmask also compiles that .cpp, so no export is
needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C++ Pull Request targeting C++

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants