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>
29 static pthread_mutex_t mutex;
34 pthread_mutex_lock (&mutex);
35 filename = tempnam (
nullptr, prefix);
36 pthread_mutex_unlock (&mutex);
40 if (access (filename.c_str(), F_OK)) {
41 unlink (filename.c_str());
46 return filename.c_str();
51 pthread_mutex_t Tempfilename::mutex = PTHREAD_MUTEX_INITIALIZER;
54 TEST(ONDISK, make_invlists) {
58 std::unordered_map<int, int> listnos;
67 std::vector<uint8_t> code(32);
68 for (
int i = 0; i < nadd; i++) {
70 int list_no = int(nlist * d * d);
71 int * ar = (
int*)code.data();
74 ivf.add_entry (list_no, i, code.data());
80 for (
int i = 0; i < nlist; i++) {
81 int size = ivf.list_size(i);
82 const long *ids = ivf.get_ids (i);
83 const uint8_t *codes = ivf.get_codes (i);
84 for (
int j = 0; j < size; j++) {
86 const int * ar = (
const int*)&codes[code_size * j];
87 EXPECT_EQ (ar[0],
id);
89 EXPECT_EQ (listnos[
id], i);
93 EXPECT_EQ (ntot, nadd);
97 TEST(ONDISK, test_add) {
99 int nlist = 30, nq = 200, nb = 1500, k = 10;
102 std::vector<float> x(d * nlist);
103 faiss::float_rand(x.data(), d * nlist, 12345);
104 quantizer.add(nlist, x.data());
106 std::vector<float> xb(d * nb);
107 faiss::float_rand(xb.data(), d * nb, 23456);
110 index.add(nb, xb.data());
112 std::vector<float> xq(d * nb);
113 faiss::float_rand(xq.data(), d * nq, 34567);
115 std::vector<float> ref_D (nq * k);
116 std::vector<faiss::Index::idx_t> ref_I (nq * k);
118 index.search (nq, xq.data(), k,
119 ref_D.data(), ref_I.data());
128 index.nlist, index.code_size,
131 index2.replace_invlists(&ivf);
133 index2.add(nb, xb.data());
135 std::vector<float> new_D (nq * k);
136 std::vector<faiss::Index::idx_t> new_I (nq * k);
138 index2.search (nq, xq.data(), k,
139 new_D.data(), new_I.data());
141 EXPECT_EQ (ref_D, new_D);
142 EXPECT_EQ (ref_I, new_I);
144 write_index(&index2, filename2.c_str());
150 faiss::Index *index3 = faiss::read_index(filename2.c_str());
152 std::vector<float> new_D (nq * k);
153 std::vector<faiss::Index::idx_t> new_I (nq * k);
155 index3->
search (nq, xq.data(), k,
156 new_D.data(), new_I.data());
158 EXPECT_EQ (ref_D, new_D);
159 EXPECT_EQ (ref_I, new_I);
169 TEST(ONDISK, make_invlists_threaded) {
181 std::vector<int> list_nos (nadd);
183 for (
int i = 0; i < nadd; i++) {
184 double d = drand48();
185 list_nos[i] = int(nlist * d * d);
190 std::vector<uint8_t> code(32);
192 for (
int i = 0; i < nadd; i++) {
193 int list_no = list_nos[i];
194 int * ar = (
int*)code.data();
197 ivf.add_entry (list_no, i, code.data());
202 for (
int i = 0; i < nlist; i++) {
203 int size = ivf.list_size(i);
204 const long *ids = ivf.get_ids (i);
205 const uint8_t *codes = ivf.get_codes (i);
206 for (
int j = 0; j < size; j++) {
208 const int * ar = (
const int*)&codes[code_size * j];
209 EXPECT_EQ (ar[0],
id);
210 EXPECT_EQ (ar[1], i);
211 EXPECT_EQ (list_nos[
id], i);
215 EXPECT_EQ (ntot, nadd);
virtual void search(idx_t n, const float *x, idx_t k, float *distances, idx_t *labels) const =0