faiss 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.h +1 -1
- data/vendor/faiss/faiss/Clustering.cpp +35 -4
- data/vendor/faiss/faiss/Clustering.h +10 -1
- data/vendor/faiss/faiss/IVFlib.cpp +4 -1
- data/vendor/faiss/faiss/Index.h +21 -6
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -1
- data/vendor/faiss/faiss/IndexFastScan.cpp +22 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +11 -7
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +159 -5
- data/vendor/faiss/faiss/IndexFlatCodes.h +20 -3
- data/vendor/faiss/faiss/IndexHNSW.cpp +143 -90
- data/vendor/faiss/faiss/IndexHNSW.h +52 -3
- data/vendor/faiss/faiss/IndexIVF.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVF.h +9 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +15 -0
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +3 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +130 -57
- data/vendor/faiss/faiss/IndexIVFFastScan.h +14 -7
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +1 -3
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +21 -2
- data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
- data/vendor/faiss/faiss/IndexLattice.h +3 -22
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -29
- data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
- data/vendor/faiss/faiss/IndexNSG.h +1 -1
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
- data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
- data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +5 -5
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +3 -1
- data/vendor/faiss/faiss/MetricType.h +7 -2
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
- data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
- data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +36 -4
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +6 -0
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +2 -8
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +2 -0
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +25 -0
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +6 -0
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +65 -0
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
- data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +25 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +9 -1
- data/vendor/faiss/faiss/impl/DistanceComputer.h +46 -0
- data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +358 -190
- data/vendor/faiss/faiss/impl/HNSW.h +43 -22
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +8 -8
- data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +13 -8
- data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +1 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +5 -1
- data/vendor/faiss/faiss/impl/ResultHandler.h +151 -32
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +719 -102
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +5 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +29 -15
- data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +28 -10
- data/vendor/faiss/faiss/impl/io.cpp +13 -5
- data/vendor/faiss/faiss/impl/io.h +4 -4
- data/vendor/faiss/faiss/impl/io_macros.h +6 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +22 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +11 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +1 -1
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +448 -1
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +5 -5
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +143 -59
- data/vendor/faiss/faiss/index_factory.cpp +31 -13
- data/vendor/faiss/faiss/index_io.h +12 -5
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +9 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +55 -17
- data/vendor/faiss/faiss/invlists/InvertedLists.h +18 -9
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +21 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -3
- data/vendor/faiss/faiss/utils/Heap.h +105 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
- data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +58 -88
- data/vendor/faiss/faiss/utils/distances.h +5 -5
- data/vendor/faiss/faiss/utils/distances_simd.cpp +997 -9
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
- data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
- data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +4 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +2 -1
- data/vendor/faiss/faiss/utils/random.cpp +43 -0
- data/vendor/faiss/faiss/utils/random.h +25 -0
- data/vendor/faiss/faiss/utils/simdlib.h +10 -1
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +5 -2
- data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
- data/vendor/faiss/faiss/utils/utils.cpp +10 -3
- data/vendor/faiss/faiss/utils/utils.h +3 -0
- metadata +16 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
|
@@ -130,20 +130,17 @@ void fvec_renorm_L2(size_t d, size_t nx, float* __restrict x) {
|
|
|
130
130
|
namespace {
|
|
131
131
|
|
|
132
132
|
/* Find the nearest neighbors for nx queries in a set of ny vectors */
|
|
133
|
-
template <class BlockResultHandler
|
|
133
|
+
template <class BlockResultHandler>
|
|
134
134
|
void exhaustive_inner_product_seq(
|
|
135
135
|
const float* x,
|
|
136
136
|
const float* y,
|
|
137
137
|
size_t d,
|
|
138
138
|
size_t nx,
|
|
139
139
|
size_t ny,
|
|
140
|
-
BlockResultHandler& res
|
|
141
|
-
const IDSelector* sel = nullptr) {
|
|
140
|
+
BlockResultHandler& res) {
|
|
142
141
|
using SingleResultHandler =
|
|
143
142
|
typename BlockResultHandler::SingleResultHandler;
|
|
144
|
-
int nt = std::min(int(nx), omp_get_max_threads());
|
|
145
|
-
|
|
146
|
-
FAISS_ASSERT(use_sel == (sel != nullptr));
|
|
143
|
+
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
147
144
|
|
|
148
145
|
#pragma omp parallel num_threads(nt)
|
|
149
146
|
{
|
|
@@ -156,7 +153,7 @@ void exhaustive_inner_product_seq(
|
|
|
156
153
|
resi.begin(i);
|
|
157
154
|
|
|
158
155
|
for (size_t j = 0; j < ny; j++, y_j += d) {
|
|
159
|
-
if (
|
|
156
|
+
if (!res.is_in_selection(j)) {
|
|
160
157
|
continue;
|
|
161
158
|
}
|
|
162
159
|
float ip = fvec_inner_product(x_i, y_j, d);
|
|
@@ -167,20 +164,17 @@ void exhaustive_inner_product_seq(
|
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
|
|
170
|
-
template <class BlockResultHandler
|
|
167
|
+
template <class BlockResultHandler>
|
|
171
168
|
void exhaustive_L2sqr_seq(
|
|
172
169
|
const float* x,
|
|
173
170
|
const float* y,
|
|
174
171
|
size_t d,
|
|
175
172
|
size_t nx,
|
|
176
173
|
size_t ny,
|
|
177
|
-
BlockResultHandler& res
|
|
178
|
-
const IDSelector* sel = nullptr) {
|
|
174
|
+
BlockResultHandler& res) {
|
|
179
175
|
using SingleResultHandler =
|
|
180
176
|
typename BlockResultHandler::SingleResultHandler;
|
|
181
|
-
int nt = std::min(int(nx), omp_get_max_threads());
|
|
182
|
-
|
|
183
|
-
FAISS_ASSERT(use_sel == (sel != nullptr));
|
|
177
|
+
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
184
178
|
|
|
185
179
|
#pragma omp parallel num_threads(nt)
|
|
186
180
|
{
|
|
@@ -191,7 +185,7 @@ void exhaustive_L2sqr_seq(
|
|
|
191
185
|
const float* y_j = y;
|
|
192
186
|
resi.begin(i);
|
|
193
187
|
for (size_t j = 0; j < ny; j++, y_j += d) {
|
|
194
|
-
if (
|
|
188
|
+
if (!res.is_in_selection(j)) {
|
|
195
189
|
continue;
|
|
196
190
|
}
|
|
197
191
|
float disij = fvec_L2sqr(x_i, y_j, d);
|
|
@@ -326,6 +320,9 @@ void exhaustive_L2sqr_blas_default_impl(
|
|
|
326
320
|
float ip = *ip_line;
|
|
327
321
|
float dis = x_norms[i] + y_norms[j] - 2 * ip;
|
|
328
322
|
|
|
323
|
+
if (!res.is_in_selection(j)) {
|
|
324
|
+
dis = HUGE_VALF;
|
|
325
|
+
}
|
|
329
326
|
// negative values can occur for identical vectors
|
|
330
327
|
// due to roundoff errors
|
|
331
328
|
if (dis < 0)
|
|
@@ -601,44 +598,40 @@ void exhaustive_L2sqr_blas<Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
|
601
598
|
#endif
|
|
602
599
|
}
|
|
603
600
|
|
|
604
|
-
|
|
605
|
-
void
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
exhaustive_L2sqr_seq(x, y, d, nx, ny, res);
|
|
619
|
-
} else {
|
|
620
|
-
exhaustive_L2sqr_blas(x, y, d, nx, ny, res, y_norm2);
|
|
601
|
+
struct Run_search_inner_product {
|
|
602
|
+
using T = void;
|
|
603
|
+
template <class BlockResultHandler>
|
|
604
|
+
void f(BlockResultHandler& res,
|
|
605
|
+
const float* x,
|
|
606
|
+
const float* y,
|
|
607
|
+
size_t d,
|
|
608
|
+
size_t nx,
|
|
609
|
+
size_t ny) {
|
|
610
|
+
if (res.sel || nx < distance_compute_blas_threshold) {
|
|
611
|
+
exhaustive_inner_product_seq(x, y, d, nx, ny, res);
|
|
612
|
+
} else {
|
|
613
|
+
exhaustive_inner_product_blas(x, y, d, nx, ny, res);
|
|
614
|
+
}
|
|
621
615
|
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
void
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
exhaustive_inner_product_blas(x, y, d, nx, ny, res);
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
struct Run_search_L2sqr {
|
|
619
|
+
using T = void;
|
|
620
|
+
template <class BlockResultHandler>
|
|
621
|
+
void f(BlockResultHandler& res,
|
|
622
|
+
const float* x,
|
|
623
|
+
const float* y,
|
|
624
|
+
size_t d,
|
|
625
|
+
size_t nx,
|
|
626
|
+
size_t ny,
|
|
627
|
+
const float* y_norm2) {
|
|
628
|
+
if (res.sel || nx < distance_compute_blas_threshold) {
|
|
629
|
+
exhaustive_L2sqr_seq(x, y, d, nx, ny, res);
|
|
630
|
+
} else {
|
|
631
|
+
exhaustive_L2sqr_blas(x, y, d, nx, ny, res, y_norm2);
|
|
632
|
+
}
|
|
640
633
|
}
|
|
641
|
-
}
|
|
634
|
+
};
|
|
642
635
|
|
|
643
636
|
} // anonymous namespace
|
|
644
637
|
|
|
@@ -675,16 +668,9 @@ void knn_inner_product(
|
|
|
675
668
|
return;
|
|
676
669
|
}
|
|
677
670
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
} else if (k < distance_compute_min_k_reservoir) {
|
|
682
|
-
HeapBlockResultHandler<CMin<float, int64_t>> res(nx, vals, ids, k);
|
|
683
|
-
knn_inner_product_select(x, y, d, nx, ny, res, sel);
|
|
684
|
-
} else {
|
|
685
|
-
ReservoirBlockResultHandler<CMin<float, int64_t>> res(nx, vals, ids, k);
|
|
686
|
-
knn_inner_product_select(x, y, d, nx, ny, res, sel);
|
|
687
|
-
}
|
|
671
|
+
Run_search_inner_product r;
|
|
672
|
+
dispatch_knn_ResultHandler(
|
|
673
|
+
nx, vals, ids, k, METRIC_INNER_PRODUCT, sel, r, x, y, d, nx, ny);
|
|
688
674
|
|
|
689
675
|
if (imin != 0) {
|
|
690
676
|
for (size_t i = 0; i < nx * k; i++) {
|
|
@@ -730,16 +716,11 @@ void knn_L2sqr(
|
|
|
730
716
|
knn_L2sqr_by_idx(x, y, sela->ids, d, nx, ny, sela->n, k, vals, ids, 0);
|
|
731
717
|
return;
|
|
732
718
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
knn_L2sqr_select(x, y, d, nx, ny, res, y_norm2, sel);
|
|
739
|
-
} else {
|
|
740
|
-
ReservoirBlockResultHandler<CMax<float, int64_t>> res(nx, vals, ids, k);
|
|
741
|
-
knn_L2sqr_select(x, y, d, nx, ny, res, y_norm2, sel);
|
|
742
|
-
}
|
|
719
|
+
|
|
720
|
+
Run_search_L2sqr r;
|
|
721
|
+
dispatch_knn_ResultHandler(
|
|
722
|
+
nx, vals, ids, k, METRIC_L2, sel, r, x, y, d, nx, ny, y_norm2);
|
|
723
|
+
|
|
743
724
|
if (imin != 0) {
|
|
744
725
|
for (size_t i = 0; i < nx * k; i++) {
|
|
745
726
|
if (ids[i] >= 0) {
|
|
@@ -766,6 +747,7 @@ void knn_L2sqr(
|
|
|
766
747
|
* Range search
|
|
767
748
|
***************************************************************************/
|
|
768
749
|
|
|
750
|
+
// TODO accept a y_norm2 as well
|
|
769
751
|
void range_search_L2sqr(
|
|
770
752
|
const float* x,
|
|
771
753
|
const float* y,
|
|
@@ -775,15 +757,9 @@ void range_search_L2sqr(
|
|
|
775
757
|
float radius,
|
|
776
758
|
RangeSearchResult* res,
|
|
777
759
|
const IDSelector* sel) {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
exhaustive_L2sqr_seq<RH, true>(x, y, d, nx, ny, resh, sel);
|
|
782
|
-
} else if (nx < distance_compute_blas_threshold) {
|
|
783
|
-
exhaustive_L2sqr_seq(x, y, d, nx, ny, resh, sel);
|
|
784
|
-
} else {
|
|
785
|
-
exhaustive_L2sqr_blas(x, y, d, nx, ny, resh);
|
|
786
|
-
}
|
|
760
|
+
Run_search_L2sqr r;
|
|
761
|
+
dispatch_range_ResultHandler(
|
|
762
|
+
res, radius, METRIC_L2, sel, r, x, y, d, nx, ny, nullptr);
|
|
787
763
|
}
|
|
788
764
|
|
|
789
765
|
void range_search_inner_product(
|
|
@@ -795,15 +771,9 @@ void range_search_inner_product(
|
|
|
795
771
|
float radius,
|
|
796
772
|
RangeSearchResult* res,
|
|
797
773
|
const IDSelector* sel) {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
exhaustive_inner_product_seq<RH, true>(x, y, d, nx, ny, resh, sel);
|
|
802
|
-
} else if (nx < distance_compute_blas_threshold) {
|
|
803
|
-
exhaustive_inner_product_seq(x, y, d, nx, ny, resh);
|
|
804
|
-
} else {
|
|
805
|
-
exhaustive_inner_product_blas(x, y, d, nx, ny, resh);
|
|
806
|
-
}
|
|
774
|
+
Run_search_inner_product r;
|
|
775
|
+
dispatch_range_ResultHandler(
|
|
776
|
+
res, radius, METRIC_INNER_PRODUCT, sel, r, x, y, d, nx, ny);
|
|
807
777
|
}
|
|
808
778
|
|
|
809
779
|
/***************************************************************************
|
|
@@ -285,7 +285,7 @@ FAISS_API extern int distance_compute_blas_database_bs;
|
|
|
285
285
|
// rather than a heap
|
|
286
286
|
FAISS_API extern int distance_compute_min_k_reservoir;
|
|
287
287
|
|
|
288
|
-
/** Return the k nearest
|
|
288
|
+
/** Return the k nearest neighbors of each of the nx vectors x among the ny
|
|
289
289
|
* vector y, w.r.t to max inner product.
|
|
290
290
|
*
|
|
291
291
|
* @param x query vectors, size nx * d
|
|
@@ -301,7 +301,7 @@ void knn_inner_product(
|
|
|
301
301
|
float_minheap_array_t* res,
|
|
302
302
|
const IDSelector* sel = nullptr);
|
|
303
303
|
|
|
304
|
-
/** Return the k nearest
|
|
304
|
+
/** Return the k nearest neighbors of each of the nx vectors x among the ny
|
|
305
305
|
* vector y, for the inner product metric.
|
|
306
306
|
*
|
|
307
307
|
* @param x query vectors, size nx * d
|
|
@@ -320,7 +320,7 @@ void knn_inner_product(
|
|
|
320
320
|
int64_t* indexes,
|
|
321
321
|
const IDSelector* sel = nullptr);
|
|
322
322
|
|
|
323
|
-
/** Return the k nearest
|
|
323
|
+
/** Return the k nearest neighbors of each of the nx vectors x among the ny
|
|
324
324
|
* vector y, for the L2 distance
|
|
325
325
|
* @param x query vectors, size nx * d
|
|
326
326
|
* @param y database vectors, size ny * d
|
|
@@ -338,7 +338,7 @@ void knn_L2sqr(
|
|
|
338
338
|
const float* y_norm2 = nullptr,
|
|
339
339
|
const IDSelector* sel = nullptr);
|
|
340
340
|
|
|
341
|
-
/** Return the k nearest
|
|
341
|
+
/** Return the k nearest neighbors of each of the nx vectors x among the ny
|
|
342
342
|
* vector y, for the L2 distance
|
|
343
343
|
*
|
|
344
344
|
* @param x query vectors, size nx * d
|
|
@@ -413,7 +413,7 @@ void knn_L2sqr_by_idx(
|
|
|
413
413
|
/// Forward declaration, see AuxIndexStructures.h
|
|
414
414
|
struct RangeSearchResult;
|
|
415
415
|
|
|
416
|
-
/** Return the k nearest
|
|
416
|
+
/** Return the k nearest neighbors of each of the nx vectors x among the ny
|
|
417
417
|
* vector y, w.r.t to max inner product
|
|
418
418
|
*
|
|
419
419
|
* @param x query vectors, size nx * d
|