14 #include <unordered_map>
17 #include <gtest/gtest.h>
19 #include <faiss/OnDiskInvertedLists.h>
20 #include <faiss/IndexIVFFlat.h>
21 #include <faiss/IndexFlat.h>
22 #include <faiss/utils.h>
23 #include <faiss/index_io.h>
30 static pthread_mutex_t mutex;
34 Tempfilename (
const char *prefix =
nullptr) {
35 pthread_mutex_lock (&mutex);
36 char *cfname = tempnam (
nullptr, prefix);
39 pthread_mutex_unlock (&mutex);
43 if (access (filename.c_str(), F_OK)) {
44 unlink (filename.c_str());
49 return filename.c_str();
54 pthread_mutex_t Tempfilename::mutex = PTHREAD_MUTEX_INITIALIZER;
59 TEST(ONDISK, make_invlists) {
63 std::unordered_map<int, int> listnos;
65 Tempfilename filename;
72 std::vector<uint8_t> code(32);
73 for (
int i = 0; i < nadd; i++) {
75 int list_no = int(nlist * d * d);
76 int * ar = (
int*)code.data();
79 ivf.add_entry (list_no, i, code.data());
85 for (
int i = 0; i < nlist; i++) {
86 int size = ivf.list_size(i);
87 const long *ids = ivf.get_ids (i);
88 const uint8_t *codes = ivf.get_codes (i);
89 for (
int j = 0; j < size; j++) {
91 const int * ar = (
const int*)&codes[code_size * j];
92 EXPECT_EQ (ar[0],
id);
94 EXPECT_EQ (listnos[
id], i);
98 EXPECT_EQ (ntot, nadd);
102 TEST(ONDISK, test_add) {
104 int nlist = 30, nq = 200, nb = 1500, k = 10;
107 std::vector<float> x(d * nlist);
108 faiss::float_rand(x.data(), d * nlist, 12345);
109 quantizer.add(nlist, x.data());
111 std::vector<float> xb(d * nb);
112 faiss::float_rand(xb.data(), d * nb, 23456);
115 index.add(nb, xb.data());
117 std::vector<float> xq(d * nb);
118 faiss::float_rand(xq.data(), d * nq, 34567);
120 std::vector<float> ref_D (nq * k);
121 std::vector<faiss::Index::idx_t> ref_I (nq * k);
123 index.search (nq, xq.data(), k,
124 ref_D.data(), ref_I.data());
126 Tempfilename filename, filename2;
133 index.nlist, index.code_size,
136 index2.replace_invlists(&ivf);
138 index2.add(nb, xb.data());
140 std::vector<float> new_D (nq * k);
141 std::vector<faiss::Index::idx_t> new_I (nq * k);
143 index2.search (nq, xq.data(), k,
144 new_D.data(), new_I.data());
146 EXPECT_EQ (ref_D, new_D);
147 EXPECT_EQ (ref_I, new_I);
149 write_index(&index2, filename2.c_str());
155 faiss::Index *index3 = faiss::read_index(filename2.c_str());
157 std::vector<float> new_D (nq * k);
158 std::vector<faiss::Index::idx_t> new_I (nq * k);
160 index3->
search (nq, xq.data(), k,
161 new_D.data(), new_I.data());
163 EXPECT_EQ (ref_D, new_D);
164 EXPECT_EQ (ref_I, new_I);
174 TEST(ONDISK, make_invlists_threaded) {
180 Tempfilename filename;
186 std::vector<int> list_nos (nadd);
188 for (
int i = 0; i < nadd; i++) {
189 double d = drand48();
190 list_nos[i] = int(nlist * d * d);
195 std::vector<uint8_t> code(32);
197 for (
int i = 0; i < nadd; i++) {
198 int list_no = list_nos[i];
199 int * ar = (
int*)code.data();
202 ivf.add_entry (list_no, i, code.data());
207 for (
int i = 0; i < nlist; i++) {
208 int size = ivf.list_size(i);
209 const long *ids = ivf.get_ids (i);
210 const uint8_t *codes = ivf.get_codes (i);
211 for (
int j = 0; j < size; j++) {
213 const int * ar = (
const int*)&codes[code_size * j];
214 EXPECT_EQ (ar[0],
id);
215 EXPECT_EQ (ar[1], i);
216 EXPECT_EQ (list_nos[
id], i);
220 EXPECT_EQ (ntot, nadd);
virtual void search(idx_t n, const float *x, idx_t k, float *distances, idx_t *labels) const =0