Skip to content

SPANN: opt-in mmap of the input vector file - #451

Open
Peng (fastio) wants to merge 2 commits into
microsoft:mainfrom
fastio:feat/mmap-vectors
Open

SPANN: opt-in mmap of the input vector file#451
Peng (fastio) wants to merge 2 commits into
microsoft:mainfrom
fastio:feat/mmap-vectors

Conversation

@fastio

Copy link
Copy Markdown

Motivation

SPANN BuildIndex currently reads the whole input vector file into heap before
SelectHead. For billion-scale inputs (e.g. SPACEV1B) that means hundreds of GB
of resident memory just to hold the raw vectors, on top of the build's own
working set. BKT clustering touches vectors randomly by id and rarely needs
them all hot at once.

Design

A new [Base] MmapVectors option (default false). When enabled and the input
is the DEFAULT binary format, DefaultVectorReader::GetVectorSet memory-maps
the file read-only instead of reading it:

  • The OS demand-pages vectors on access and reclaims clean file-backed pages
    under memory pressure, so peak RSS stays bounded.
  • The mapping is wrapped in a small header-only RAII class
    (Helper::MemoryMappedFile, Windows + POSIX). Its lifetime follows the
    returned VectorSet via an aliasing shared_ptr, so the mapping is unmapped
    exactly once, after the last ByteArray copy is gone.
  • MADV_RANDOM is applied on POSIX to suppress readahead, matching BKT's
    random access pattern.

Fallback and safety

  • If mapping fails for any reason, the reader falls back to
    in-memory read with a warning.
  • The mapping is read-only, but SelectHead normalizes vecto
    the metric is Cosine and the input is not pre-normalized. BuildIndex
    detects that combination, disables mmap, and logs a warni
    to pre-normalize or use L2. L2 and pre-normalized Cosine inputs use mmap
    unmodified.

Add Helper::MemoryMappedFile (header-only RAII, read-only, Windows/POSIX)
and a [Base] MmapVectors option (default false). When enabled, the
DEFAULT-format vector file is memory-mapped instead of loaded into heap:
the OS demand-pages it and reclaims clean pages under pressure, so peak
RSS during SelectHead stays bounded on billion-scale inputs. The mapping's
lifetime follows the returned VectorSet via an aliasing shared_ptr, and
MADV_RANDOM suppresses readahead for the random access pattern of BKT
clustering.

Falls back to the regular in-memory read (with a warning) if mapping
fails. Automatically disabled for Cosine with un-normalized input, since
SelectHead normalizes vectors in place and the mapping is read-only;
pre-normalize the input or use L2 to combine the two.
Make the non-TBB ConcurrentQueue/Set/Map fallbacks expose the TBB API
surface used by ExtraFileController/ExtraDynamicSearcher (unsafe_size,
empty, unsafe_begin/end, value_type, range iteration). Force the
LoggerHolder pre-C++20 path so std::atomic<std::shared_ptr<Logger>>
never instantiates under libc++. Drop an unused omp.h include and pass
.c_str() to a SPTAGLIB_LOG variadic call.
@fastio

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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.

2 participants