faiss 0.6.2 → 0.6.3
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.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +4 -5
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +2 -4
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +10 -11
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +17 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +40 -22
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexShards.cpp +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +109 -152
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +9 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +34 -22
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +44 -36
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +168 -67
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +25 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +258 -57
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +20 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
- data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/index_read.cpp +376 -36
- data/vendor/faiss/faiss/impl/index_write.cpp +55 -4
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +85 -23
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +16 -16
- data/vendor/faiss/faiss/impl/simd_dispatch.h +30 -9
- data/vendor/faiss/faiss/index_factory.cpp +32 -6
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +31 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +15 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +1 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +92 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_levels.cpp +44 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +16 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include <faiss/impl/HNSW.h>
|
|
9
9
|
|
|
10
|
+
#include <array>
|
|
10
11
|
#include <cinttypes>
|
|
11
12
|
#include <cstddef>
|
|
12
13
|
#include <cstdlib>
|
|
@@ -172,17 +173,21 @@ void HNSW::print_neighbor_stats(int level) const {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
void HNSW::fill_with_random_links(size_t n) {
|
|
175
|
-
|
|
176
|
+
if (n == 0) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
max_level = prepare_level_tab(n);
|
|
180
|
+
entry_point = 0;
|
|
181
|
+
|
|
176
182
|
RandomGenerator rng2(456);
|
|
177
183
|
|
|
178
|
-
for (int level =
|
|
184
|
+
for (int level = max_level - 1; level >= 0; --level) {
|
|
179
185
|
std::vector<int> elts;
|
|
180
186
|
for (size_t i = 0; i < n; i++) {
|
|
181
187
|
if (levels[i] > level) {
|
|
182
188
|
elts.push_back(i);
|
|
183
189
|
}
|
|
184
190
|
}
|
|
185
|
-
printf("linking %zd elements in level %d\n", elts.size(), level);
|
|
186
191
|
|
|
187
192
|
if (elts.size() == 1) {
|
|
188
193
|
continue;
|
|
@@ -1092,8 +1097,8 @@ int hnsw_detail::search_from_candidates_panorama(
|
|
|
1092
1097
|
const SearchParameters* params) {
|
|
1093
1098
|
// Panorama's progressive-bound math is L2-specific: refuse to run in
|
|
1094
1099
|
// similarity mode.
|
|
1095
|
-
|
|
1096
|
-
|
|
1100
|
+
FAISS_THROW_IF_MSG(
|
|
1101
|
+
hnsw.is_similarity,
|
|
1097
1102
|
"search_from_candidates_panorama does not support is_similarity=true");
|
|
1098
1103
|
|
|
1099
1104
|
using C = HNSW::C_distance;
|
|
@@ -1132,177 +1137,129 @@ int hnsw_detail::search_from_candidates_panorama(
|
|
|
1132
1137
|
flat_codes_qdis,
|
|
1133
1138
|
"DistanceComputer must be a FlatCodesDistanceComputer");
|
|
1134
1139
|
|
|
1135
|
-
|
|
1136
|
-
size_t
|
|
1137
|
-
|
|
1138
|
-
|
|
1140
|
+
const auto& pano = panorama_index->pano;
|
|
1141
|
+
const size_t nb_per_parent = static_cast<size_t>(hnsw.nb_neighbors(level));
|
|
1142
|
+
const size_t num_panorama_levels = pano.n_levels;
|
|
1143
|
+
const size_t level_width_floats = pano.level_width_floats;
|
|
1139
1144
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
float
|
|
1145
|
+
constexpr size_t kTargetBatch = 64;
|
|
1146
|
+
const size_t buf_cap = kTargetBatch + nb_per_parent;
|
|
1147
|
+
std::vector<uint32_t> index_array(buf_cap);
|
|
1148
|
+
std::vector<float> exact_distances(buf_cap);
|
|
1149
|
+
std::vector<float> dot_buffer(buf_cap);
|
|
1150
|
+
std::vector<float> query_cum_sums_buf(num_panorama_levels + 1);
|
|
1144
1151
|
|
|
1145
|
-
|
|
1152
|
+
const float* query = flat_codes_qdis->q;
|
|
1146
1153
|
const size_t d = static_cast<size_t>(panorama_index->d);
|
|
1147
1154
|
|
|
1148
|
-
|
|
1149
|
-
|
|
1155
|
+
const float* cum_base = panorama_index->get_cum_sum(0);
|
|
1156
|
+
const size_t cum_stride = num_panorama_levels + 1;
|
|
1157
|
+
const auto* flat_storage =
|
|
1158
|
+
static_cast<const IndexFlat*>(panorama_index->storage);
|
|
1159
|
+
const float* xb_base =
|
|
1160
|
+
reinterpret_cast<const float*>(flat_storage->codes.data());
|
|
1161
|
+
const size_t feat_stride = d;
|
|
1150
1162
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
if (do_dis_check) {
|
|
1156
|
-
// tricky stopping condition: there are more than ef
|
|
1157
|
-
// distances that are processed already that are smaller
|
|
1158
|
-
// than d0
|
|
1163
|
+
pano.compute_query_cum_sums(query, query_cum_sums_buf.data());
|
|
1164
|
+
const float* query_cum_sums = query_cum_sums_buf.data();
|
|
1165
|
+
const float query_norm_sq = query_cum_sums[0] * query_cum_sums[0];
|
|
1159
1166
|
|
|
1160
|
-
|
|
1161
|
-
if (n_dis_below >= efSearch) {
|
|
1162
|
-
break;
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1167
|
+
int nstep = 0;
|
|
1165
1168
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1169
|
+
PanoramaStats local_pano_stats;
|
|
1170
|
+
local_pano_stats.reset();
|
|
1168
1171
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
// that are not selected.
|
|
1172
|
+
bool stop_flag = false;
|
|
1173
|
+
while (candidates.size() > 0 && !stop_flag) {
|
|
1172
1174
|
size_t initial_size = 0;
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1175
|
+
size_t k_popped = 0;
|
|
1176
|
+
while (initial_size < kTargetBatch && candidates.size() > 0) {
|
|
1177
|
+
float d0 = 0;
|
|
1178
|
+
int v0 = candidates.pop_min(&d0);
|
|
1179
|
+
if (do_dis_check) {
|
|
1180
|
+
int n_dis_below = candidates.count_below(d0);
|
|
1181
|
+
if (n_dis_below >= efSearch) {
|
|
1182
|
+
if (k_popped == 0) {
|
|
1183
|
+
// Standard early-stop: nothing queued this
|
|
1184
|
+
// iteration, terminate the outer loop entirely
|
|
1185
|
+
// (matches the single-pop path's behavior).
|
|
1186
|
+
stop_flag = true;
|
|
1187
|
+
} else {
|
|
1188
|
+
// We already have parents queued; un-pop this
|
|
1189
|
+
// one so the next outer iteration sees it and
|
|
1190
|
+
// re-applies the stop check from a clean state.
|
|
1191
|
+
candidates.push(v0, d0);
|
|
1192
|
+
}
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1177
1195
|
}
|
|
1196
|
+
k_popped++;
|
|
1178
1197
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1198
|
+
size_t begin, end;
|
|
1199
|
+
hnsw.neighbor_range(v0, level, &begin, &end);
|
|
1200
|
+
for (size_t j = begin; j < end; j++) {
|
|
1201
|
+
int v1 = hnsw.neighbors[j];
|
|
1202
|
+
if (v1 < 0) {
|
|
1203
|
+
break;
|
|
1204
|
+
}
|
|
1183
1205
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1206
|
+
bool is_new = vt.set(v1);
|
|
1207
|
+
bool is_selected = !sel || sel->is_member(v1);
|
|
1208
|
+
if (is_new && is_selected) {
|
|
1209
|
+
const float vsum =
|
|
1210
|
+
cum_base[static_cast<size_t>(v1) * cum_stride];
|
|
1211
|
+
index_array[initial_size] = v1;
|
|
1212
|
+
exact_distances[initial_size] = query_norm_sq + vsum * vsum;
|
|
1213
|
+
initial_size++;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1186
1216
|
}
|
|
1187
1217
|
|
|
1188
1218
|
local_pano_stats.total_dims += initial_size * d;
|
|
1219
|
+
|
|
1189
1220
|
size_t batch_size = initial_size;
|
|
1190
1221
|
size_t curr_panorama_level = 0;
|
|
1191
|
-
const size_t num_panorama_levels = panorama_index->pano.n_levels;
|
|
1192
1222
|
while (curr_panorama_level < num_panorama_levels && batch_size > 0) {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
size_t
|
|
1198
|
-
|
|
1199
|
-
end_dim = std::min(end_dim,
|
|
1223
|
+
const size_t cs_level_idx = curr_panorama_level + 1;
|
|
1224
|
+
const float query_cum_norm = query_cum_sums[cs_level_idx];
|
|
1225
|
+
const float two_qc = 2.0f * query_cum_norm;
|
|
1226
|
+
|
|
1227
|
+
const size_t start_dim = curr_panorama_level * level_width_floats;
|
|
1228
|
+
size_t end_dim = (curr_panorama_level + 1) * level_width_floats;
|
|
1229
|
+
end_dim = std::min(end_dim, d);
|
|
1230
|
+
const size_t dim_span = end_dim - start_dim;
|
|
1231
|
+
|
|
1232
|
+
const float* level_base = xb_base + start_dim;
|
|
1233
|
+
with_level_width(dim_span, [&]<size_t W>() {
|
|
1234
|
+
compute_level_dot_kernel<false, W>(
|
|
1235
|
+
query + start_dim,
|
|
1236
|
+
level_base,
|
|
1237
|
+
index_array.data(),
|
|
1238
|
+
batch_size,
|
|
1239
|
+
dim_span,
|
|
1240
|
+
dot_buffer.data(),
|
|
1241
|
+
feat_stride);
|
|
1242
|
+
});
|
|
1243
|
+
ndis += batch_size;
|
|
1200
1244
|
|
|
1201
|
-
size_t i = 0;
|
|
1202
1245
|
size_t next_batch_size = 0;
|
|
1203
|
-
for (; i + 3 < batch_size; i += 4) {
|
|
1204
|
-
idx_t idx_0 = index_array[i];
|
|
1205
|
-
idx_t idx_1 = index_array[i + 1];
|
|
1206
|
-
idx_t idx_2 = index_array[i + 2];
|
|
1207
|
-
idx_t idx_3 = index_array[i + 3];
|
|
1208
|
-
|
|
1209
|
-
float dp[4];
|
|
1210
|
-
flat_codes_qdis->partial_dot_product_batch_4(
|
|
1211
|
-
idx_0,
|
|
1212
|
-
idx_1,
|
|
1213
|
-
idx_2,
|
|
1214
|
-
idx_3,
|
|
1215
|
-
dp[0],
|
|
1216
|
-
dp[1],
|
|
1217
|
-
dp[2],
|
|
1218
|
-
dp[3],
|
|
1219
|
-
start_dim,
|
|
1220
|
-
end_dim - start_dim);
|
|
1221
|
-
ndis += 4;
|
|
1222
1246
|
|
|
1223
|
-
|
|
1224
|
-
float
|
|
1225
|
-
float
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
float
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
idx_2)[curr_panorama_level + 1];
|
|
1234
|
-
float cum_sum_3 = panorama_index->get_cum_sum(
|
|
1235
|
-
idx_3)[curr_panorama_level + 1];
|
|
1236
|
-
|
|
1237
|
-
float cs_bound_0 = 2.0f * cum_sum_0 * query_cum_norm;
|
|
1238
|
-
float cs_bound_1 = 2.0f * cum_sum_1 * query_cum_norm;
|
|
1239
|
-
float cs_bound_2 = 2.0f * cum_sum_2 * query_cum_norm;
|
|
1240
|
-
float cs_bound_3 = 2.0f * cum_sum_3 * query_cum_norm;
|
|
1241
|
-
|
|
1242
|
-
float lower_bound_0 = new_exact_0 - cs_bound_0;
|
|
1243
|
-
float lower_bound_1 = new_exact_1 - cs_bound_1;
|
|
1244
|
-
float lower_bound_2 = new_exact_2 - cs_bound_2;
|
|
1245
|
-
float lower_bound_3 = new_exact_3 - cs_bound_3;
|
|
1246
|
-
|
|
1247
|
-
// The following code is not the most branch friendly (due to
|
|
1248
|
-
// the maintenance of the candidate heap), but micro-benchmarks
|
|
1249
|
-
// have shown that it is not worth it to write horrible code to
|
|
1250
|
-
// squeeze out those cycles.
|
|
1251
|
-
if (!C::cmp(lower_bound_0, threshold)) {
|
|
1252
|
-
exact_distances[next_batch_size] = new_exact_0;
|
|
1253
|
-
index_array[next_batch_size] = idx_0;
|
|
1254
|
-
next_batch_size += 1;
|
|
1247
|
+
for (size_t i = 0; i < batch_size; i++) {
|
|
1248
|
+
float ne = exact_distances[i] - 2.0f * dot_buffer[i];
|
|
1249
|
+
float cum = cum_base
|
|
1250
|
+
[static_cast<size_t>(index_array[i]) * cum_stride +
|
|
1251
|
+
cs_level_idx];
|
|
1252
|
+
float lb = ne - two_qc * cum;
|
|
1253
|
+
if (lb <= threshold) {
|
|
1254
|
+
exact_distances[next_batch_size] = ne;
|
|
1255
|
+
index_array[next_batch_size] = index_array[i];
|
|
1256
|
+
next_batch_size++;
|
|
1255
1257
|
} else {
|
|
1256
|
-
candidates.push(
|
|
1257
|
-
}
|
|
1258
|
-
if (!C::cmp(lower_bound_1, threshold)) {
|
|
1259
|
-
exact_distances[next_batch_size] = new_exact_1;
|
|
1260
|
-
index_array[next_batch_size] = idx_1;
|
|
1261
|
-
next_batch_size += 1;
|
|
1262
|
-
} else {
|
|
1263
|
-
candidates.push(idx_1, new_exact_1);
|
|
1264
|
-
}
|
|
1265
|
-
if (!C::cmp(lower_bound_2, threshold)) {
|
|
1266
|
-
exact_distances[next_batch_size] = new_exact_2;
|
|
1267
|
-
index_array[next_batch_size] = idx_2;
|
|
1268
|
-
next_batch_size += 1;
|
|
1269
|
-
} else {
|
|
1270
|
-
candidates.push(idx_2, new_exact_2);
|
|
1271
|
-
}
|
|
1272
|
-
if (!C::cmp(lower_bound_3, threshold)) {
|
|
1273
|
-
exact_distances[next_batch_size] = new_exact_3;
|
|
1274
|
-
index_array[next_batch_size] = idx_3;
|
|
1275
|
-
next_batch_size += 1;
|
|
1276
|
-
} else {
|
|
1277
|
-
candidates.push(idx_3, new_exact_3);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
// Process the remaining candidates.
|
|
1282
|
-
for (; i < batch_size; i++) {
|
|
1283
|
-
idx_t idx = index_array[i];
|
|
1284
|
-
|
|
1285
|
-
float dp = flat_codes_qdis->partial_dot_product(
|
|
1286
|
-
idx, start_dim, end_dim - start_dim);
|
|
1287
|
-
ndis += 1;
|
|
1288
|
-
float new_exact = exact_distances[i] - 2.0f * dp;
|
|
1289
|
-
|
|
1290
|
-
float cum_sum = panorama_index->get_cum_sum(
|
|
1291
|
-
idx)[curr_panorama_level + 1];
|
|
1292
|
-
float cs_bound = 2.0f * cum_sum * query_cum_norm;
|
|
1293
|
-
float lower_bound = new_exact - cs_bound;
|
|
1294
|
-
|
|
1295
|
-
if (!C::cmp(lower_bound, threshold)) {
|
|
1296
|
-
exact_distances[next_batch_size] = new_exact;
|
|
1297
|
-
index_array[next_batch_size] = idx;
|
|
1298
|
-
next_batch_size += 1;
|
|
1299
|
-
} else {
|
|
1300
|
-
candidates.push(idx, new_exact);
|
|
1258
|
+
candidates.push(index_array[i], ne);
|
|
1301
1259
|
}
|
|
1302
1260
|
}
|
|
1303
1261
|
|
|
1304
|
-
local_pano_stats.total_dims_scanned +=
|
|
1305
|
-
batch_size * (end_dim - start_dim);
|
|
1262
|
+
local_pano_stats.total_dims_scanned += batch_size * dim_span;
|
|
1306
1263
|
batch_size = next_batch_size;
|
|
1307
1264
|
curr_panorama_level++;
|
|
1308
1265
|
}
|
|
@@ -1317,7 +1274,7 @@ int hnsw_detail::search_from_candidates_panorama(
|
|
|
1317
1274
|
candidates.push(idx, exact_distances[i]);
|
|
1318
1275
|
}
|
|
1319
1276
|
|
|
1320
|
-
nstep
|
|
1277
|
+
nstep += static_cast<int>(k_popped);
|
|
1321
1278
|
if (!do_dis_check && nstep > efSearch) {
|
|
1322
1279
|
break;
|
|
1323
1280
|
}
|
|
@@ -597,8 +597,8 @@ void LocalSearchQuantizer::icm_encode_step(
|
|
|
597
597
|
const float* binaries,
|
|
598
598
|
size_t n,
|
|
599
599
|
size_t n_iters) const {
|
|
600
|
-
|
|
601
|
-
FAISS_THROW_IF_NOT(binaries
|
|
600
|
+
FAISS_THROW_IF_MSG(M == 0 || K == 0, "M and K must be nonzero");
|
|
601
|
+
FAISS_THROW_IF_NOT(binaries);
|
|
602
602
|
|
|
603
603
|
// Resolve SIMD level once, not per iteration of the n × n_iters × M loop.
|
|
604
604
|
with_simd_level_256bit([&]<SIMDLevel SL>() {
|
|
@@ -142,7 +142,9 @@ void NSG::build(
|
|
|
142
142
|
idx_t n,
|
|
143
143
|
const nsg::Graph<idx_t>& knn_graph,
|
|
144
144
|
bool verbose) {
|
|
145
|
-
|
|
145
|
+
FAISS_THROW_IF_MSG(
|
|
146
|
+
is_built || ntotal != 0,
|
|
147
|
+
"NSG graph must be empty and not yet built");
|
|
146
148
|
|
|
147
149
|
if (verbose) {
|
|
148
150
|
printf("NSG::build R=%d, L=%d, C=%d\n", R, L, C);
|
|
@@ -49,18 +49,20 @@ static inline void compute_level_dot_kernel(
|
|
|
49
49
|
const uint32_t* active_indices,
|
|
50
50
|
const size_t num_active,
|
|
51
51
|
const size_t level_width_dims,
|
|
52
|
-
float* FAISS_RESTRICT dot_products
|
|
52
|
+
float* FAISS_RESTRICT dot_products,
|
|
53
|
+
size_t stride = 0) {
|
|
53
54
|
const size_t width = LevelWidth > 0 ? LevelWidth : level_width_dims;
|
|
55
|
+
const size_t row_stride = stride == 0 ? width : stride;
|
|
54
56
|
size_t i = 0;
|
|
55
57
|
for (; i + 4 <= num_active; i += 4) {
|
|
56
58
|
const float* y0 = level_storage +
|
|
57
|
-
(AllActive ? (i + 0) : active_indices[i + 0]) *
|
|
59
|
+
(AllActive ? (i + 0) : active_indices[i + 0]) * row_stride;
|
|
58
60
|
const float* y1 = level_storage +
|
|
59
|
-
(AllActive ? (i + 1) : active_indices[i + 1]) *
|
|
61
|
+
(AllActive ? (i + 1) : active_indices[i + 1]) * row_stride;
|
|
60
62
|
const float* y2 = level_storage +
|
|
61
|
-
(AllActive ? (i + 2) : active_indices[i + 2]) *
|
|
63
|
+
(AllActive ? (i + 2) : active_indices[i + 2]) * row_stride;
|
|
62
64
|
const float* y3 = level_storage +
|
|
63
|
-
(AllActive ? (i + 3) : active_indices[i + 3]) *
|
|
65
|
+
(AllActive ? (i + 3) : active_indices[i + 3]) * row_stride;
|
|
64
66
|
|
|
65
67
|
float dp0 = 0, dp1 = 0, dp2 = 0, dp3 = 0;
|
|
66
68
|
FAISS_PRAGMA_IMPRECISE_LOOP
|
|
@@ -78,8 +80,8 @@ static inline void compute_level_dot_kernel(
|
|
|
78
80
|
dot_products[i + 3] = dp3;
|
|
79
81
|
}
|
|
80
82
|
for (; i < num_active; i++) {
|
|
81
|
-
const float* yj =
|
|
82
|
-
|
|
83
|
+
const float* yj = level_storage +
|
|
84
|
+
(AllActive ? i : active_indices[i]) * row_stride;
|
|
83
85
|
float dp = 0;
|
|
84
86
|
FAISS_PRAGMA_IMPRECISE_LOOP
|
|
85
87
|
for (size_t j = 0; j < width; j++) {
|