code: def range_search_gpu(xq, r2, index_gpu, index_cpu, gpu_k=1024):
      """GPU does not support range search, so we emulate it with
      knn search + fallback to CPU index.
  
      The index_cpu can either be:
      - a CPU index that supports range search
      - a numpy table, that will be used to construct a Flat index if needed.
      - None. In that case, at most gpu_k results will be returned
      """
      nq, d = xq.shape
      is_binary_index = isinstance(index_gpu, faiss.IndexBinary)
      keep_max = faiss.is_similarity_metric(index_gpu.metric_type)
      r2 = int(r2) if is_binary_index else float(r2)
      k = min(index_gpu.ntotal, gpu_k)
      LOG.debug(
          f"GPU search {nq} queries with {k=:} {is_binary_index=:} {keep_max=:}"
      )
      t0 = time.time()
      D, I = index_gpu.search(xq, k)
      t1 = time.time() - t0
      if is_binary_index:
          assert d * 8 < 32768  # let's compact the distance matrix
          D = D.astype("int16")
      t2 = 0
      lim_remain = None
      if index_cpu is not None:
          if not keep_max:
              mask = D[:, k - 1] < r2
          else:
              mask = D[:, k - 1] > r2
          if mask.sum() > 0:
              LOG.debug("CPU search remain %d" % mask.sum())
              t0 = time.time()
              if isinstance(index_cpu, np.ndarray):
                  # then it in fact an array that we have to make flat
                  xb = index_cpu
                  if is_binary_index:
                      index_cpu = faiss.IndexBinaryFlat(d * 8)
                  else:
                      index_cpu = faiss.IndexFlat(
                          d, index_gpu.metric_type
                      )
                  index_cpu.add(xb)
              lim_remain, D_remain, I_remain = index_cpu.range_search(
                  xq[mask], r2
              )
              if is_binary_index:
                  D_remain = D_remain.astype("int16")
              t2 = time.time() - t0
      LOG.debug("combine")
      t0 = time.time()
  
      CombinerRangeKNN = (
          faiss.CombinerRangeKNNint16
          if is_binary_index
          else faiss.CombinerRangeKNNfloat
      )
  
      combiner = CombinerRangeKNN(nq, k, r2, keep_max)
      if True:
          sp = faiss.swig_ptr
          combiner.I = sp(I)
          combiner.D = sp(D)
          # combiner.set_knn_result(sp(I), sp(D))
          if lim_remain is not None:
              combiner.mask = sp(mask)
              combiner.D_remain = sp(D_remain)
              combiner.lim_remain = sp(lim_remain.view("int64"))
              combiner.I_remain = sp(I_remain)
              # combiner.set_range_result(sp(mask), sp(lim_remain.view("int64")), sp(D_remain), sp(I_remain))
          L_res = np.empty(nq + 1, dtype="int64")
          combiner.compute_sizes(sp(L_res))
          nres = L_res[-1]
          D_res = np.empty(nres, dtype=D.dtype)
          I_res = np.empty(nres, dtype="int64")
          combiner.write_result(sp(D_res), sp(I_res))
      else:
          D_res, I_res = [], []
          nr = 0
          for i in range(nq):
              if not mask[i]:
                  if index_gpu.metric_type == faiss.METRIC_L2:
                      nv = (D[i, :] < r2).sum()
                  else:
                      nv = (D[i, :] > r2).sum()
                  D_res.append(D[i, :nv])
                  I_res.append(I[i, :nv])
              else:
                  l0, l1 = lim_remain[nr], lim_remain[nr + 1]
                  D_res.append(D_remain[l0:l1])
                  I_res.append(I_remain[l0:l1])
                  nr += 1
          L_res = np.cumsum([0] + [len(di) for di in D_res])
          D_res = np.hstack(D_res)
          I_res = np.hstack(I_res)
      t3 = time.time() - t0
      LOG.debug(f"times {t1:.3f}s {t2:.3f}s {t3:.3f}s")
      return L_res, D_res, I_res
  
file_path: faiss/contrib/exhaustive_search.py
imports: import faiss
  import time
  import numpy
  import logging
label_desc: Use image node_id 2 for calling a global function with example usage: range_search_gpu(xq, r2, index_gpu, index_cpu, gpu_k) and returns: L_res,  D_res,  I_res