class_docstr: manages a local index, that does the coarse quantization and a set
  of sub_indexes. The sub_indexes search a subset of the inverted
  lists. The SplitPerListIndex merges results from the sub-indexes
class_docstr_tok: ["manages","a","local","index",",","that","does","the","coarse","quantization","and","a","set","of","sub_indexes",".","The","sub_indexes","search","a","subset","of","the","inverted","lists",".","The","SplitPerListIndex","merges","results","from","the","sub-indexes"]
code: def search(self, x, k):
      xqo, list_nos, coarse_dis = self.index.transform_and_assign(x)
      assign = self.balance_lists(list_nos)
  
      def do_query(i):
          sub_index = self.sub_indexes[i]
          list_nos_i = list_nos.copy()
          list_nos_i[assign != i] = -1
          t0 = time.time()
          Di, Ii = sub_index.ivf_search_preassigned(
              xqo, list_nos_i, coarse_dis, k
          )
          # print(list_nos_i, Ii)
          if self.verbose:
              print("client %d: %.3f s" % (i, time.time() - t0))
          return Di, Ii
  
      rh = ResultHeap(x.shape[0], k)
  
      for Di, Ii in self.pool.imap(do_query, range(self.ni)):
          # print("ADD", Ii, rh.I)
          rh.add_batch_result(Di, Ii, 0)
      rh.finalize()
      return rh.D, rh.I
  
imports: import time
  from faiss.contrib import rpc
  import combined_index
  import argparse
  from multiprocessing.pool import ThreadPool
  import faiss
  import numpy
label_desc: Use image node_id 7 for calling the SplitPerListIndex obj's underlying member method code with example usage: obj.search(x, k) and returns: rh,  rh, Di,  Ii