faiss 0.1.3 → 0.1.4
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/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +36 -33
- data/vendor/faiss/faiss/AutoTune.h +6 -3
- data/vendor/faiss/faiss/Clustering.cpp +16 -12
- data/vendor/faiss/faiss/Index.cpp +3 -4
- data/vendor/faiss/faiss/Index.h +3 -3
- data/vendor/faiss/faiss/IndexBinary.cpp +3 -4
- data/vendor/faiss/faiss/IndexBinary.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +2 -12
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -2
- data/vendor/faiss/faiss/IndexFlat.cpp +0 -148
- data/vendor/faiss/faiss/IndexFlat.h +0 -51
- data/vendor/faiss/faiss/IndexHNSW.cpp +4 -5
- data/vendor/faiss/faiss/IndexIVF.cpp +118 -31
- data/vendor/faiss/faiss/IndexIVF.h +22 -15
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +39 -15
- data/vendor/faiss/faiss/IndexIVFPQ.h +25 -9
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1116 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +166 -0
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +8 -9
- data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +34 -18
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +536 -0
- data/vendor/faiss/faiss/IndexPQFastScan.h +111 -0
- data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -0
- data/vendor/faiss/faiss/IndexPreTransform.h +2 -0
- data/vendor/faiss/faiss/IndexRefine.cpp +256 -0
- data/vendor/faiss/faiss/IndexRefine.h +73 -0
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuDistance.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +16 -9
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +8 -1
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +19 -2
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +28 -2
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +24 -14
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +29 -2
- data/vendor/faiss/faiss/gpu/GpuResources.h +4 -0
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +60 -27
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +28 -6
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +547 -0
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +51 -0
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +3 -3
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +3 -2
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +274 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +7 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +5 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +231 -0
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +33 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -0
- data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +6 -0
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +5 -6
- data/vendor/faiss/faiss/gpu/utils/Timer.h +2 -2
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +5 -4
- data/vendor/faiss/faiss/impl/HNSW.cpp +2 -4
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +4 -4
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +22 -12
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -0
- data/vendor/faiss/faiss/impl/ResultHandler.h +452 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -19
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +6 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +64 -96
- data/vendor/faiss/faiss/impl/index_write.cpp +34 -25
- data/vendor/faiss/faiss/impl/io.cpp +33 -2
- data/vendor/faiss/faiss/impl/io.h +7 -2
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -15
- data/vendor/faiss/faiss/impl/platform_macros.h +44 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +272 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +169 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +180 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +354 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +559 -0
- data/vendor/faiss/faiss/index_factory.cpp +112 -7
- data/vendor/faiss/faiss/index_io.h +1 -48
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +151 -0
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +76 -0
- data/vendor/faiss/faiss/{DirectMap.cpp → invlists/DirectMap.cpp} +1 -1
- data/vendor/faiss/faiss/{DirectMap.h → invlists/DirectMap.h} +1 -1
- data/vendor/faiss/faiss/{InvertedLists.cpp → invlists/InvertedLists.cpp} +72 -1
- data/vendor/faiss/faiss/{InvertedLists.h → invlists/InvertedLists.h} +32 -1
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +107 -0
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +63 -0
- data/vendor/faiss/faiss/{OnDiskInvertedLists.cpp → invlists/OnDiskInvertedLists.cpp} +21 -6
- data/vendor/faiss/faiss/{OnDiskInvertedLists.h → invlists/OnDiskInvertedLists.h} +5 -2
- data/vendor/faiss/faiss/python/python_callbacks.h +8 -1
- data/vendor/faiss/faiss/utils/AlignedTable.h +141 -0
- data/vendor/faiss/faiss/utils/Heap.cpp +2 -4
- data/vendor/faiss/faiss/utils/Heap.h +61 -50
- data/vendor/faiss/faiss/utils/distances.cpp +164 -319
- data/vendor/faiss/faiss/utils/distances.h +28 -20
- data/vendor/faiss/faiss/utils/distances_simd.cpp +277 -49
- data/vendor/faiss/faiss/utils/extra_distances.cpp +1 -2
- data/vendor/faiss/faiss/utils/hamming-inl.h +4 -4
- data/vendor/faiss/faiss/utils/hamming.cpp +3 -6
- data/vendor/faiss/faiss/utils/hamming.h +2 -7
- data/vendor/faiss/faiss/utils/ordered_key_value.h +98 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +1256 -0
- data/vendor/faiss/faiss/utils/partitioning.h +69 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +277 -0
- data/vendor/faiss/faiss/utils/quantize_lut.h +80 -0
- data/vendor/faiss/faiss/utils/simdlib.h +31 -0
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +461 -0
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +589 -0
- metadata +43 -141
- data/vendor/faiss/benchs/bench_6bit_codec.cpp +0 -80
- data/vendor/faiss/c_api/AutoTune_c.cpp +0 -83
- data/vendor/faiss/c_api/AutoTune_c.h +0 -66
- data/vendor/faiss/c_api/Clustering_c.cpp +0 -145
- data/vendor/faiss/c_api/Clustering_c.h +0 -123
- data/vendor/faiss/c_api/IndexFlat_c.cpp +0 -140
- data/vendor/faiss/c_api/IndexFlat_c.h +0 -115
- data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +0 -64
- data/vendor/faiss/c_api/IndexIVFFlat_c.h +0 -58
- data/vendor/faiss/c_api/IndexIVF_c.cpp +0 -99
- data/vendor/faiss/c_api/IndexIVF_c.h +0 -142
- data/vendor/faiss/c_api/IndexLSH_c.cpp +0 -37
- data/vendor/faiss/c_api/IndexLSH_c.h +0 -40
- data/vendor/faiss/c_api/IndexPreTransform_c.cpp +0 -21
- data/vendor/faiss/c_api/IndexPreTransform_c.h +0 -32
- data/vendor/faiss/c_api/IndexShards_c.cpp +0 -38
- data/vendor/faiss/c_api/IndexShards_c.h +0 -39
- data/vendor/faiss/c_api/Index_c.cpp +0 -105
- data/vendor/faiss/c_api/Index_c.h +0 -183
- data/vendor/faiss/c_api/MetaIndexes_c.cpp +0 -49
- data/vendor/faiss/c_api/MetaIndexes_c.h +0 -49
- data/vendor/faiss/c_api/clone_index_c.cpp +0 -23
- data/vendor/faiss/c_api/clone_index_c.h +0 -32
- data/vendor/faiss/c_api/error_c.h +0 -42
- data/vendor/faiss/c_api/error_impl.cpp +0 -27
- data/vendor/faiss/c_api/error_impl.h +0 -16
- data/vendor/faiss/c_api/faiss_c.h +0 -58
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +0 -98
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +0 -56
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +0 -52
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +0 -68
- data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +0 -17
- data/vendor/faiss/c_api/gpu/GpuIndex_c.h +0 -30
- data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +0 -38
- data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +0 -86
- data/vendor/faiss/c_api/gpu/GpuResources_c.h +0 -66
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +0 -54
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +0 -53
- data/vendor/faiss/c_api/gpu/macros_impl.h +0 -42
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +0 -220
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +0 -149
- data/vendor/faiss/c_api/index_factory_c.cpp +0 -26
- data/vendor/faiss/c_api/index_factory_c.h +0 -30
- data/vendor/faiss/c_api/index_io_c.cpp +0 -42
- data/vendor/faiss/c_api/index_io_c.h +0 -50
- data/vendor/faiss/c_api/macros_impl.h +0 -110
- data/vendor/faiss/demos/demo_imi_flat.cpp +0 -154
- data/vendor/faiss/demos/demo_imi_pq.cpp +0 -203
- data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +0 -151
- data/vendor/faiss/demos/demo_sift1M.cpp +0 -252
- data/vendor/faiss/demos/demo_weighted_kmeans.cpp +0 -185
- data/vendor/faiss/misc/test_blas.cpp +0 -87
- data/vendor/faiss/tests/test_binary_flat.cpp +0 -62
- data/vendor/faiss/tests/test_dealloc_invlists.cpp +0 -188
- data/vendor/faiss/tests/test_ivfpq_codec.cpp +0 -70
- data/vendor/faiss/tests/test_ivfpq_indexing.cpp +0 -100
- data/vendor/faiss/tests/test_lowlevel_ivf.cpp +0 -573
- data/vendor/faiss/tests/test_merge.cpp +0 -260
- data/vendor/faiss/tests/test_omp_threads.cpp +0 -14
- data/vendor/faiss/tests/test_ondisk_ivf.cpp +0 -225
- data/vendor/faiss/tests/test_pairs_decoding.cpp +0 -193
- data/vendor/faiss/tests/test_params_override.cpp +0 -236
- data/vendor/faiss/tests/test_pq_encoding.cpp +0 -98
- data/vendor/faiss/tests/test_sliding_ivf.cpp +0 -246
- data/vendor/faiss/tests/test_threaded_index.cpp +0 -253
- data/vendor/faiss/tests/test_transfer_invlists.cpp +0 -159
- data/vendor/faiss/tutorial/cpp/1-Flat.cpp +0 -104
- data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +0 -85
- data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +0 -98
- data/vendor/faiss/tutorial/cpp/4-GPU.cpp +0 -122
- data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +0 -104
@@ -0,0 +1,180 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
|
9
|
+
#include <faiss/impl/pq4_fast_scan.h>
|
10
|
+
|
11
|
+
#include <faiss/impl/FaissAssert.h>
|
12
|
+
#include <faiss/impl/simd_result_handlers.h>
|
13
|
+
|
14
|
+
|
15
|
+
namespace faiss {
|
16
|
+
|
17
|
+
|
18
|
+
using namespace simd_result_handlers;
|
19
|
+
|
20
|
+
/***************************************************************
|
21
|
+
* accumulation functions
|
22
|
+
***************************************************************/
|
23
|
+
|
24
|
+
namespace {
|
25
|
+
|
26
|
+
/*
|
27
|
+
* The computation kernel
|
28
|
+
* It accumulates results for NQ queries and BB * 32 database elements
|
29
|
+
* writes results in a ResultHandler
|
30
|
+
*/
|
31
|
+
|
32
|
+
template<int NQ, int BB, class ResultHandler>
|
33
|
+
void kernel_accumulate_block(
|
34
|
+
int nsq,
|
35
|
+
const uint8_t *codes,
|
36
|
+
const uint8_t *LUT,
|
37
|
+
ResultHandler & res)
|
38
|
+
{
|
39
|
+
// distance accumulators
|
40
|
+
simd16uint16 accu[NQ][BB][4];
|
41
|
+
|
42
|
+
for(int q = 0; q < NQ; q++) {
|
43
|
+
for(int b = 0; b < BB; b++) {
|
44
|
+
accu[q][b][0].clear();
|
45
|
+
accu[q][b][1].clear();
|
46
|
+
accu[q][b][2].clear();
|
47
|
+
accu[q][b][3].clear();
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
for(int sq = 0; sq < nsq; sq += 2) {
|
52
|
+
simd32uint8 lut_cache[NQ];
|
53
|
+
for(int q = 0; q < NQ; q++) {
|
54
|
+
lut_cache[q] = simd32uint8(LUT);
|
55
|
+
LUT += 32;
|
56
|
+
}
|
57
|
+
|
58
|
+
for (int b = 0; b < BB; b++) {
|
59
|
+
simd32uint8 c = simd32uint8(codes);
|
60
|
+
codes += 32;
|
61
|
+
simd32uint8 mask(15);
|
62
|
+
simd32uint8 chi = simd32uint8(simd16uint16(c) >> 4) & mask;
|
63
|
+
simd32uint8 clo = c & mask;
|
64
|
+
|
65
|
+
for(int q = 0; q < NQ; q++) {
|
66
|
+
simd32uint8 lut = lut_cache[q];
|
67
|
+
simd32uint8 res0 = lut.lookup_2_lanes(clo);
|
68
|
+
simd32uint8 res1 = lut.lookup_2_lanes(chi);
|
69
|
+
|
70
|
+
accu[q][b][0] += simd16uint16(res0);
|
71
|
+
accu[q][b][1] += simd16uint16(res0) >> 8;
|
72
|
+
|
73
|
+
accu[q][b][2] += simd16uint16(res1);
|
74
|
+
accu[q][b][3] += simd16uint16(res1) >> 8;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
for(int q = 0; q < NQ; q++) {
|
80
|
+
for (int b = 0; b < BB; b++) {
|
81
|
+
|
82
|
+
accu[q][b][0] -= accu[q][b][1] << 8;
|
83
|
+
simd16uint16 dis0 = combine2x2(accu[q][b][0], accu[q][b][1]);
|
84
|
+
|
85
|
+
accu[q][b][2] -= accu[q][b][3] << 8;
|
86
|
+
simd16uint16 dis1 = combine2x2(accu[q][b][2], accu[q][b][3]);
|
87
|
+
|
88
|
+
res.handle(q, b, dis0, dis1);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
template<int NQ, int BB, class ResultHandler>
|
97
|
+
void accumulate_fixed_blocks(
|
98
|
+
size_t nb,
|
99
|
+
int nsq,
|
100
|
+
const uint8_t *codes,
|
101
|
+
const uint8_t *LUT,
|
102
|
+
ResultHandler & res)
|
103
|
+
{
|
104
|
+
constexpr int bbs = 32 * BB;
|
105
|
+
for (int64_t j0 = 0; j0 < nb; j0 += bbs) {
|
106
|
+
FixedStorageHandler<NQ, 2 * BB> res2;
|
107
|
+
kernel_accumulate_block<NQ, BB>(nsq, codes, LUT, res2);
|
108
|
+
res.set_block_origin(0, j0);
|
109
|
+
res2.to_other_handler(res);
|
110
|
+
codes += bbs * nsq / 2;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
} // anonymous namespace
|
116
|
+
|
117
|
+
template<class ResultHandler>
|
118
|
+
void pq4_accumulate_loop(
|
119
|
+
int nq,
|
120
|
+
size_t nb, int bbs,
|
121
|
+
int nsq,
|
122
|
+
const uint8_t *codes,
|
123
|
+
const uint8_t *LUT,
|
124
|
+
ResultHandler & res)
|
125
|
+
{
|
126
|
+
FAISS_THROW_IF_NOT(is_aligned_pointer(codes));
|
127
|
+
FAISS_THROW_IF_NOT(is_aligned_pointer(LUT));
|
128
|
+
FAISS_THROW_IF_NOT(bbs % 32 == 0);
|
129
|
+
FAISS_THROW_IF_NOT(nb % bbs == 0);
|
130
|
+
|
131
|
+
#define DISPATCH(NQ, BB) \
|
132
|
+
case NQ * 1000 + BB: \
|
133
|
+
accumulate_fixed_blocks<NQ, BB>(nb, nsq, codes, LUT, res); \
|
134
|
+
break
|
135
|
+
|
136
|
+
switch(nq * 1000 + bbs / 32) {
|
137
|
+
DISPATCH(1, 1);
|
138
|
+
DISPATCH(1, 2);
|
139
|
+
DISPATCH(1, 3);
|
140
|
+
DISPATCH(1, 4);
|
141
|
+
DISPATCH(1, 5);
|
142
|
+
DISPATCH(2, 1);
|
143
|
+
DISPATCH(2, 2);
|
144
|
+
DISPATCH(3, 1);
|
145
|
+
DISPATCH(4, 1);
|
146
|
+
default:
|
147
|
+
FAISS_THROW_FMT("nq=%d bbs=%d not instantiated", nq, bbs);
|
148
|
+
}
|
149
|
+
#undef DISPATCH
|
150
|
+
|
151
|
+
}
|
152
|
+
|
153
|
+
// explicit template instantiations
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
#define INSTANTIATE_ACCUMULATE(TH, C, with_id_map) \
|
159
|
+
template void pq4_accumulate_loop<TH<C, with_id_map>> \
|
160
|
+
(int, size_t, int, int, const uint8_t *, const uint8_t *, TH<C, with_id_map> &);
|
161
|
+
|
162
|
+
#define INSTANTIATE_3(C, with_id_map) \
|
163
|
+
INSTANTIATE_ACCUMULATE(SingleResultHandler, C, with_id_map) \
|
164
|
+
INSTANTIATE_ACCUMULATE(HeapHandler, C, with_id_map) \
|
165
|
+
INSTANTIATE_ACCUMULATE(ReservoirHandler, C, with_id_map) \
|
166
|
+
|
167
|
+
using Csi = CMax<uint16_t, int>;
|
168
|
+
INSTANTIATE_3(Csi, false);
|
169
|
+
using CsiMin = CMin<uint16_t, int>;
|
170
|
+
INSTANTIATE_3(CsiMin, false);
|
171
|
+
|
172
|
+
using Csl = CMax<uint16_t, int64_t>;
|
173
|
+
INSTANTIATE_3(Csl, true);
|
174
|
+
using CslMin = CMin<uint16_t, int64_t>;
|
175
|
+
INSTANTIATE_3(CslMin, true);
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
} // namespace faiss
|
180
|
+
|
@@ -0,0 +1,354 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <faiss/impl/pq4_fast_scan.h>
|
9
|
+
|
10
|
+
#include <faiss/impl/FaissAssert.h>
|
11
|
+
#include <faiss/utils/simdlib.h>
|
12
|
+
#include <faiss/impl/simd_result_handlers.h>
|
13
|
+
|
14
|
+
|
15
|
+
namespace faiss {
|
16
|
+
|
17
|
+
|
18
|
+
using namespace simd_result_handlers;
|
19
|
+
|
20
|
+
/************************************************************
|
21
|
+
* Accumulation functions
|
22
|
+
************************************************************/
|
23
|
+
|
24
|
+
namespace {
|
25
|
+
|
26
|
+
/*
|
27
|
+
* The computation kernel
|
28
|
+
* It accumulates results for NQ queries and 2 * 16 database elements
|
29
|
+
* writes results in a ResultHandler
|
30
|
+
*/
|
31
|
+
|
32
|
+
template<int NQ, class ResultHandler>
|
33
|
+
void kernel_accumulate_block(
|
34
|
+
int nsq,
|
35
|
+
const uint8_t *codes,
|
36
|
+
const uint8_t *LUT,
|
37
|
+
ResultHandler & res)
|
38
|
+
{
|
39
|
+
// dummy alloc to keep the windows compiler happy
|
40
|
+
constexpr int NQA = NQ > 0 ? NQ : 1;
|
41
|
+
// distance accumulators
|
42
|
+
simd16uint16 accu[NQA][4];
|
43
|
+
|
44
|
+
for(int q = 0; q < NQ; q++) {
|
45
|
+
for(int b = 0; b < 4; b++) {
|
46
|
+
accu[q][b].clear();
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
// _mm_prefetch(codes + 768, 0);
|
51
|
+
for(int sq = 0; sq < nsq; sq += 2) {
|
52
|
+
|
53
|
+
// prefetch
|
54
|
+
simd32uint8 c(codes);
|
55
|
+
codes += 32;
|
56
|
+
|
57
|
+
simd32uint8 mask(0xf);
|
58
|
+
// shift op does not exist for int8...
|
59
|
+
simd32uint8 chi = simd32uint8(simd16uint16(c) >> 4) & mask;
|
60
|
+
simd32uint8 clo = c & mask;
|
61
|
+
|
62
|
+
for(int q = 0; q < NQ; q++) {
|
63
|
+
// load LUTs for 2 quantizers
|
64
|
+
simd32uint8 lut(LUT);
|
65
|
+
LUT += 32;
|
66
|
+
|
67
|
+
simd32uint8 res0 = lut.lookup_2_lanes(clo);
|
68
|
+
simd32uint8 res1 = lut.lookup_2_lanes(chi);
|
69
|
+
|
70
|
+
accu[q][0] += simd16uint16(res0);
|
71
|
+
accu[q][1] += simd16uint16(res0) >> 8;
|
72
|
+
|
73
|
+
accu[q][2] += simd16uint16(res1);
|
74
|
+
accu[q][3] += simd16uint16(res1) >> 8;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
for(int q = 0; q < NQ; q++) {
|
79
|
+
accu[q][0] -= accu[q][1] << 8;
|
80
|
+
simd16uint16 dis0 = combine2x2(accu[q][0], accu[q][1]);
|
81
|
+
accu[q][2] -= accu[q][3] << 8;
|
82
|
+
simd16uint16 dis1 = combine2x2(accu[q][2], accu[q][3]);
|
83
|
+
res.handle(q, 0, dis0, dis1);
|
84
|
+
}
|
85
|
+
|
86
|
+
}
|
87
|
+
|
88
|
+
// handle at most 4 blocks of queries
|
89
|
+
template<int QBS, class ResultHandler>
|
90
|
+
void accumulate_q_4step(
|
91
|
+
size_t ntotal2,
|
92
|
+
int nsq,
|
93
|
+
const uint8_t *codes,
|
94
|
+
const uint8_t *LUT0,
|
95
|
+
ResultHandler & res)
|
96
|
+
{
|
97
|
+
|
98
|
+
constexpr int Q1 = QBS & 15;
|
99
|
+
constexpr int Q2 = (QBS >> 4) & 15;
|
100
|
+
constexpr int Q3 = (QBS >> 8) & 15;
|
101
|
+
constexpr int Q4 = (QBS >> 12) & 15;
|
102
|
+
constexpr int SQ = Q1 + Q2 + Q3 + Q4;
|
103
|
+
|
104
|
+
for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
|
105
|
+
FixedStorageHandler<SQ, 2> res2;
|
106
|
+
const uint8_t *LUT = LUT0;
|
107
|
+
kernel_accumulate_block<Q1>(nsq, codes, LUT, res2);
|
108
|
+
LUT += Q1 * nsq * 16;
|
109
|
+
if (Q2 > 0) {
|
110
|
+
res2.set_block_origin(Q1, 0);
|
111
|
+
kernel_accumulate_block<Q2>(nsq, codes, LUT, res2);
|
112
|
+
LUT += Q2 * nsq * 16;
|
113
|
+
}
|
114
|
+
if (Q3 > 0) {
|
115
|
+
res2.set_block_origin(Q1 + Q2, 0);
|
116
|
+
kernel_accumulate_block<Q3>(nsq, codes, LUT, res2);
|
117
|
+
LUT += Q3 * nsq * 16;
|
118
|
+
}
|
119
|
+
if (Q4 > 0) {
|
120
|
+
res2.set_block_origin(Q1 + Q2 + Q3, 0);
|
121
|
+
kernel_accumulate_block<Q4>(nsq, codes, LUT, res2);
|
122
|
+
}
|
123
|
+
res.set_block_origin(0, j0);
|
124
|
+
res2.to_other_handler(res);
|
125
|
+
codes += 32 * nsq / 2;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
template<int NQ, class ResultHandler>
|
133
|
+
void kernel_accumulate_block_loop(
|
134
|
+
size_t ntotal2,
|
135
|
+
int nsq,
|
136
|
+
const uint8_t *codes,
|
137
|
+
const uint8_t *LUT,
|
138
|
+
ResultHandler & res)
|
139
|
+
{
|
140
|
+
|
141
|
+
for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
|
142
|
+
res.set_block_origin(0, j0);
|
143
|
+
kernel_accumulate_block<NQ, ResultHandler>
|
144
|
+
(nsq, codes + j0 * nsq / 2, LUT, res);
|
145
|
+
}
|
146
|
+
|
147
|
+
}
|
148
|
+
|
149
|
+
// non-template version of accumulate kernel -- dispatches dynamically
|
150
|
+
template<class ResultHandler>
|
151
|
+
void accumulate(
|
152
|
+
int nq,
|
153
|
+
size_t ntotal2,
|
154
|
+
int nsq,
|
155
|
+
const uint8_t *codes,
|
156
|
+
const uint8_t *LUT,
|
157
|
+
ResultHandler & res)
|
158
|
+
{
|
159
|
+
|
160
|
+
assert(nsq % 2 == 0);
|
161
|
+
assert(is_aligned_pointer(codes));
|
162
|
+
assert(is_aligned_pointer(LUT));
|
163
|
+
|
164
|
+
#define DISPATCH(NQ) \
|
165
|
+
case NQ: \
|
166
|
+
kernel_accumulate_block_loop<NQ, ResultHandler> \
|
167
|
+
(ntotal2, nsq, codes, LUT, res); \
|
168
|
+
return
|
169
|
+
|
170
|
+
switch(nq) {
|
171
|
+
DISPATCH(1);
|
172
|
+
DISPATCH(2);
|
173
|
+
DISPATCH(3);
|
174
|
+
DISPATCH(4);
|
175
|
+
}
|
176
|
+
FAISS_THROW_FMT("accumulate nq=%d not instanciated",
|
177
|
+
nq);
|
178
|
+
|
179
|
+
#undef DISPATCH
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
} // anonumous namespace
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
template<class ResultHandler>
|
188
|
+
void pq4_accumulate_loop_qbs(
|
189
|
+
int qbs,
|
190
|
+
size_t ntotal2,
|
191
|
+
int nsq,
|
192
|
+
const uint8_t *codes,
|
193
|
+
const uint8_t *LUT0,
|
194
|
+
ResultHandler & res)
|
195
|
+
{
|
196
|
+
|
197
|
+
assert(nsq % 2 == 0);
|
198
|
+
assert(is_aligned_pointer(codes));
|
199
|
+
assert(is_aligned_pointer(LUT0));
|
200
|
+
|
201
|
+
// try out optimized versions
|
202
|
+
switch(qbs) {
|
203
|
+
#define DISPATCH(QBS) \
|
204
|
+
case QBS: accumulate_q_4step<QBS> \
|
205
|
+
(ntotal2, nsq, codes, LUT0, res); \
|
206
|
+
return;
|
207
|
+
DISPATCH(0x3333); // 12
|
208
|
+
DISPATCH(0x2333); // 11
|
209
|
+
DISPATCH(0x2233); // 10
|
210
|
+
DISPATCH(0x333); // 9
|
211
|
+
DISPATCH(0x2223); // 9
|
212
|
+
DISPATCH(0x233); // 8
|
213
|
+
DISPATCH(0x1223); // 8
|
214
|
+
DISPATCH(0x223); // 7
|
215
|
+
DISPATCH(0x34); // 7
|
216
|
+
DISPATCH(0x133); // 7
|
217
|
+
DISPATCH(0x6); // 6
|
218
|
+
DISPATCH(0x33); // 6
|
219
|
+
DISPATCH(0x123); // 6
|
220
|
+
DISPATCH(0x222); // 6
|
221
|
+
DISPATCH(0x23); // 5
|
222
|
+
DISPATCH(0x5); // 5
|
223
|
+
DISPATCH(0x13); // 4
|
224
|
+
DISPATCH(0x22); // 4
|
225
|
+
DISPATCH(0x4); // 4
|
226
|
+
DISPATCH(0x3); // 3
|
227
|
+
DISPATCH(0x21); // 3
|
228
|
+
DISPATCH(0x2); // 2
|
229
|
+
DISPATCH(0x1); // 1
|
230
|
+
#undef DISPATCH
|
231
|
+
}
|
232
|
+
|
233
|
+
// default implementation where qbs is not known at compile time
|
234
|
+
|
235
|
+
for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
|
236
|
+
const uint8_t *LUT = LUT0;
|
237
|
+
int qi = qbs;
|
238
|
+
int i0 = 0;
|
239
|
+
while(qi) {
|
240
|
+
int nq = qi & 15;
|
241
|
+
qi >>= 4;
|
242
|
+
res.set_block_origin(i0, j0);
|
243
|
+
#define DISPATCH(NQ) \
|
244
|
+
case NQ: \
|
245
|
+
kernel_accumulate_block<NQ, ResultHandler> \
|
246
|
+
(nsq, codes, LUT, res); \
|
247
|
+
break
|
248
|
+
switch(nq) {
|
249
|
+
DISPATCH(1);
|
250
|
+
DISPATCH(2);
|
251
|
+
DISPATCH(3);
|
252
|
+
DISPATCH(4);
|
253
|
+
#undef DISPATCH
|
254
|
+
default:
|
255
|
+
FAISS_THROW_FMT("accumulate nq=%d not instanciated",
|
256
|
+
nq);
|
257
|
+
}
|
258
|
+
i0 += nq;
|
259
|
+
LUT += nq * nsq * 16;
|
260
|
+
}
|
261
|
+
codes += 32 * nsq / 2;
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
+
// explicit template instantiations
|
268
|
+
|
269
|
+
|
270
|
+
#define INSTANTIATE_ACCUMULATE_Q(RH) \
|
271
|
+
template void pq4_accumulate_loop_qbs<RH> \
|
272
|
+
(int, size_t, int, const uint8_t *, const uint8_t *, RH &);
|
273
|
+
|
274
|
+
using Csi = CMax<uint16_t, int>;
|
275
|
+
INSTANTIATE_ACCUMULATE_Q(SingleResultHandler<Csi>)
|
276
|
+
INSTANTIATE_ACCUMULATE_Q(HeapHandler<Csi>)
|
277
|
+
INSTANTIATE_ACCUMULATE_Q(ReservoirHandler<Csi>)
|
278
|
+
using Csi2 = CMin<uint16_t, int>;
|
279
|
+
INSTANTIATE_ACCUMULATE_Q(SingleResultHandler<Csi2>)
|
280
|
+
INSTANTIATE_ACCUMULATE_Q(HeapHandler<Csi2>)
|
281
|
+
INSTANTIATE_ACCUMULATE_Q(ReservoirHandler<Csi2>)
|
282
|
+
|
283
|
+
using Cfl = CMax<uint16_t, int64_t>;
|
284
|
+
using HHCsl = HeapHandler<Cfl, true>;
|
285
|
+
using RHCsl = ReservoirHandler<Cfl, true>;
|
286
|
+
using SHCsl = SingleResultHandler<Cfl, true>;
|
287
|
+
INSTANTIATE_ACCUMULATE_Q(HHCsl)
|
288
|
+
INSTANTIATE_ACCUMULATE_Q(RHCsl)
|
289
|
+
INSTANTIATE_ACCUMULATE_Q(SHCsl)
|
290
|
+
using Cfl2 = CMin<uint16_t, int64_t>;
|
291
|
+
using HHCsl2 = HeapHandler<Cfl2, true>;
|
292
|
+
using RHCsl2 = ReservoirHandler<Cfl2, true>;
|
293
|
+
using SHCsl2 = SingleResultHandler<Cfl2, true>;
|
294
|
+
INSTANTIATE_ACCUMULATE_Q(HHCsl2)
|
295
|
+
INSTANTIATE_ACCUMULATE_Q(RHCsl2)
|
296
|
+
INSTANTIATE_ACCUMULATE_Q(SHCsl2)
|
297
|
+
|
298
|
+
|
299
|
+
/***************************************************************
|
300
|
+
* Packing functions
|
301
|
+
***************************************************************/
|
302
|
+
|
303
|
+
int pq4_qbs_to_nq(int qbs) {
|
304
|
+
int i0 = 0;
|
305
|
+
int qi = qbs;
|
306
|
+
while(qi) {
|
307
|
+
int nq = qi & 15;
|
308
|
+
qi >>= 4;
|
309
|
+
i0 += nq;
|
310
|
+
}
|
311
|
+
return i0;
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
void accumulate_to_mem(
|
317
|
+
int nq,
|
318
|
+
size_t ntotal2,
|
319
|
+
int nsq,
|
320
|
+
const uint8_t *codes,
|
321
|
+
const uint8_t *LUT,
|
322
|
+
uint16_t* accu)
|
323
|
+
{
|
324
|
+
FAISS_THROW_IF_NOT(ntotal2 % 32 == 0);
|
325
|
+
StoreResultHandler handler(accu, ntotal2);
|
326
|
+
accumulate(nq, ntotal2, nsq, codes, LUT, handler);
|
327
|
+
}
|
328
|
+
|
329
|
+
|
330
|
+
int pq4_preferred_qbs(int n) {
|
331
|
+
// from timmings in P141901742, P141902828
|
332
|
+
static int map[12] = {
|
333
|
+
0, 1, 2, 3, 0x13,
|
334
|
+
0x23, 0x33, 0x223, 0x233, 0x333,
|
335
|
+
0x2233, 0x2333
|
336
|
+
};
|
337
|
+
if (n <= 11) {
|
338
|
+
return map[n];
|
339
|
+
} else if (n <= 24) {
|
340
|
+
// override qbs: all first stages with 3 steps
|
341
|
+
// then 1 stage with the rest
|
342
|
+
int nbit = 4 * (n / 3); // nbits with only 3s
|
343
|
+
int qbs = 0x33333333 & ((1 << nbit) - 1);
|
344
|
+
qbs |= (n % 3) << nbit;
|
345
|
+
return qbs;
|
346
|
+
} else {
|
347
|
+
FAISS_THROW_FMT("number of queries %d too large", n);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
|
351
|
+
|
352
|
+
|
353
|
+
} // namespace faiss
|
354
|
+
|