@@ -257,6 +257,12 @@ struct OnDiskInvertedLists::OngoingPrefetch {
257257int OnDiskInvertedLists::OngoingPrefetch::global_cs = 0 ;
258258
259259void OnDiskInvertedLists::prefetch_lists (const idx_t * list_nos, int n) const {
260+
261+ // avoid prefetch when the ondisk-ivf is already prepared for read-only paths
262+ // helpful when the queries are not batched
263+ if (skip_prefetch) {
264+ return ;
265+ }
260266 pf->prefetch_lists (list_nos, n);
261267}
262268
@@ -353,6 +359,8 @@ OnDiskInvertedLists::OnDiskInvertedLists(
353359 filename (filename),
354360 totsize(0 ),
355361 ptr(nullptr ),
362+ pre_mapped(false ),
363+ skip_prefetch(false ),
356364 read_only(false ),
357365 locks(new LockLevels()),
358366 pf(new OngoingPrefetch(this )),
@@ -369,11 +377,16 @@ OnDiskInvertedLists::~OnDiskInvertedLists() {
369377
370378 // unmap all lists
371379 if (ptr != nullptr ) {
372- int err = munmap (ptr, totsize);
373- if (err != 0 ) {
374- fprintf (stderr, " mumap error: %s" , strerror (errno));
380+ if (!pre_mapped) {
381+ int err = munmap (ptr, totsize);
382+ if (err != 0 ) {
383+ fprintf (stderr, " mumap error: %s" , strerror (errno));
384+ }
385+ } else {
386+ ptr = nullptr ;
375387 }
376388 }
389+
377390 delete locks;
378391}
379392
@@ -741,10 +754,48 @@ InvertedLists* OnDiskInvertedListsIOHook::read(IOReader* f, int io_flags)
741754 return od;
742755}
743756
757+ /* *
758+ * This function is just an alternate way to use the OnDiskInvertedLists.
759+ * It's useful when the index is read using BufIOReader from a uint8_t* buffer
760+ * which is already mmap'd by the application layer.
761+ * All the responbility of handling this mmap pointer now falls on the app layer
762+ **/
763+ InvertedLists* read_ArrayInvertedLists_MMAP (
764+ IOReader* f,
765+ OnDiskInvertedLists* ails,
766+ const std::vector<size_t >& sizes) {
767+
768+ // setting this true is to ensure that the destructor does not unmap
769+ // since the mmap control is on the parent layer of faiss.
770+ ails->pre_mapped = true ;
771+
772+ BufIOReader* reader = dynamic_cast <BufIOReader*>(f);
773+ FAISS_THROW_IF_NOT_MSG (reader, " reading over mmap'd region is supported only with BufIOReader" );
774+
775+ size_t o = reader->rp ;
776+ ails->totsize = reader->buf_size ;
777+ FAISS_THROW_IF_NOT (o <= ails->totsize );
778+ FAISS_THROW_IF_NOT_MSG (reader->buf , " reader buffer is null" );
779+ // using the base pointer to the mmap'd region
780+ ails->ptr = const_cast <uint8_t *>(reader->buf );
781+
782+ for (size_t i = 0 ; i < ails->nlist ; i++) {
783+ OnDiskInvertedLists::List& l = ails->lists [i];
784+ l.size = l.capacity = sizes[i];
785+ l.offset = o;
786+ o += l.size * (sizeof (idx_t ) + ails->code_size );
787+ }
788+
789+ // updating the read pointer appropriately, this is needed when the IVF
790+ // wrapped with another index class.
791+ reader->rp = o;
792+ return ails;
793+ }
794+
744795/* * read from a ArrayInvertedLists into this invertedlist type */
745796InvertedLists* OnDiskInvertedListsIOHook::read_ArrayInvertedLists (
746797 IOReader* f,
747- int /* io_flags */ ,
798+ int io_flags,
748799 size_t nlist,
749800 size_t code_size,
750801 const std::vector<size_t >& sizes) const {
@@ -753,6 +804,13 @@ InvertedLists* OnDiskInvertedListsIOHook::read_ArrayInvertedLists(
753804 ails->code_size = code_size;
754805 ails->read_only = true ;
755806 ails->lists .resize (nlist);
807+ if (io_flags & IO_FLAG_SKIP_PREFETCH) {
808+ ails->skip_prefetch = true ;
809+ }
810+
811+ if (io_flags & IO_FLAG_READ_MMAP) {
812+ return read_ArrayInvertedLists_MMAP (f, ails, sizes);
813+ }
756814
757815 FileIOReader* reader = dynamic_cast <FileIOReader*>(f);
758816 FAISS_THROW_IF_NOT_MSG (reader, " mmap only supported for File objects" );
0 commit comments