hnswlib 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/hnswlib/src/bruteforce.h +2 -2
- data/ext/hnswlib/src/hnswalg.h +51 -38
- data/ext/hnswlib/src/hnswlib.h +9 -0
- data/ext/hnswlib/src/space_ip.h +36 -3
- data/ext/hnswlib/src/space_l2.h +38 -4
- data/ext/hnswlib/src/visited_list_pool.h +1 -0
- data/lib/hnswlib/version.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec8d1a750f703968418f3aca9beffc33c061c9c5e7e6d24050a8aa8cd15e0d35
|
4
|
+
data.tar.gz: e8bb3c9b706dfd6d6d25d5f471970b50a6f191efbe9719437d0ce00c0c7a1420
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f39ec12aac12a0af0a4882f092c61b29417d14c575580b821ccb2154568e9c04e6a4170617cfa0185ca32dc322181cd18dd116bd527fc3f61b52cee3180b648
|
7
|
+
data.tar.gz: e355334afba1ed2f8817e2dda8eedd4bc61670f08ea349e44b7259c01584a195e2bb33f3de9f2f5d4ce59cd6cb80bd17b7f0c3b5e5dedd26dd0d8880c75d25ad
|
data/CHANGELOG.md
CHANGED
@@ -92,13 +92,13 @@ namespace hnswlib {
|
|
92
92
|
searchKnn(const void *query_data, size_t k) const {
|
93
93
|
std::priority_queue<std::pair<dist_t, labeltype >> topResults;
|
94
94
|
if (cur_element_count == 0) return topResults;
|
95
|
-
for (
|
95
|
+
for (int i = 0; i < k; i++) {
|
96
96
|
dist_t dist = fstdistfunc_(query_data, data_ + size_per_element_ * i, dist_func_param_);
|
97
97
|
topResults.push(std::pair<dist_t, labeltype>(dist, *((labeltype *) (data_ + size_per_element_ * i +
|
98
98
|
data_size_))));
|
99
99
|
}
|
100
100
|
dist_t lastdist = topResults.top().first;
|
101
|
-
for (
|
101
|
+
for (int i = k; i < cur_element_count; i++) {
|
102
102
|
dist_t dist = fstdistfunc_(query_data, data_ + size_per_element_ * i, dist_func_param_);
|
103
103
|
if (dist <= lastdist) {
|
104
104
|
topResults.push(std::pair<dist_t, labeltype>(dist, *((labeltype *) (data_ + size_per_element_ * i +
|
data/ext/hnswlib/src/hnswalg.h
CHANGED
@@ -19,7 +19,6 @@ namespace hnswlib {
|
|
19
19
|
static const tableint max_update_element_locks = 65536;
|
20
20
|
HierarchicalNSW() : visited_list_pool_(nullptr), data_level0_memory_(nullptr), linkLists_(nullptr), cur_element_count(0) { }
|
21
21
|
HierarchicalNSW(SpaceInterface<dist_t> *s) {
|
22
|
-
|
23
22
|
}
|
24
23
|
|
25
24
|
HierarchicalNSW(SpaceInterface<dist_t> *s, const std::string &location, bool nmslib = false, size_t max_elements=0) {
|
@@ -30,7 +29,7 @@ namespace hnswlib {
|
|
30
29
|
link_list_locks_(max_elements), link_list_update_locks_(max_update_element_locks), element_levels_(max_elements) {
|
31
30
|
max_elements_ = max_elements;
|
32
31
|
|
33
|
-
|
32
|
+
num_deleted_ = 0;
|
34
33
|
data_size_ = s->get_data_size();
|
35
34
|
fstdistfunc_ = s->get_dist_func();
|
36
35
|
dist_func_param_ = s->get_dist_func_param();
|
@@ -57,8 +56,6 @@ namespace hnswlib {
|
|
57
56
|
|
58
57
|
visited_list_pool_ = new VisitedListPool(1, max_elements);
|
59
58
|
|
60
|
-
|
61
|
-
|
62
59
|
//initializations for special treatment of the first node
|
63
60
|
enterpoint_node_ = -1;
|
64
61
|
maxlevel_ = -1;
|
@@ -93,6 +90,7 @@ namespace hnswlib {
|
|
93
90
|
size_t cur_element_count;
|
94
91
|
size_t size_data_per_element_;
|
95
92
|
size_t size_links_per_element_;
|
93
|
+
size_t num_deleted_;
|
96
94
|
|
97
95
|
size_t M_;
|
98
96
|
size_t maxM_;
|
@@ -113,20 +111,15 @@ namespace hnswlib {
|
|
113
111
|
std::vector<std::mutex> link_list_update_locks_;
|
114
112
|
tableint enterpoint_node_;
|
115
113
|
|
116
|
-
|
117
114
|
size_t size_links_level0_;
|
118
115
|
size_t offsetData_, offsetLevel0_;
|
119
116
|
|
120
|
-
|
121
117
|
char *data_level0_memory_;
|
122
118
|
char **linkLists_;
|
123
119
|
std::vector<int> element_levels_;
|
124
120
|
|
125
121
|
size_t data_size_;
|
126
122
|
|
127
|
-
bool has_deletions_;
|
128
|
-
|
129
|
-
|
130
123
|
size_t label_offset_;
|
131
124
|
DISTFUNC<dist_t> fstdistfunc_;
|
132
125
|
void *dist_func_param_;
|
@@ -183,7 +176,7 @@ namespace hnswlib {
|
|
183
176
|
|
184
177
|
while (!candidateSet.empty()) {
|
185
178
|
std::pair<dist_t, tableint> curr_el_pair = candidateSet.top();
|
186
|
-
if ((-curr_el_pair.first) > lowerBound) {
|
179
|
+
if ((-curr_el_pair.first) > lowerBound && top_candidates.size() == ef_construction_) {
|
187
180
|
break;
|
188
181
|
}
|
189
182
|
candidateSet.pop();
|
@@ -272,7 +265,7 @@ namespace hnswlib {
|
|
272
265
|
|
273
266
|
std::pair<dist_t, tableint> current_node_pair = candidate_set.top();
|
274
267
|
|
275
|
-
if ((-current_node_pair.first) > lowerBound) {
|
268
|
+
if ((-current_node_pair.first) > lowerBound && (top_candidates.size() == ef || has_deletions == false)) {
|
276
269
|
break;
|
277
270
|
}
|
278
271
|
candidate_set.pop();
|
@@ -548,7 +541,7 @@ namespace hnswlib {
|
|
548
541
|
}
|
549
542
|
}
|
550
543
|
|
551
|
-
if (
|
544
|
+
if (num_deleted_) {
|
552
545
|
std::priority_queue<std::pair<dist_t, tableint >> top_candidates1=searchBaseLayerST<true>(currObj, query_data,
|
553
546
|
ef_);
|
554
547
|
top_candidates.swap(top_candidates1);
|
@@ -624,8 +617,6 @@ namespace hnswlib {
|
|
624
617
|
}
|
625
618
|
|
626
619
|
void loadIndex(const std::string &location, SpaceInterface<dist_t> *s, size_t max_elements_i=0) {
|
627
|
-
|
628
|
-
|
629
620
|
std::ifstream input(location, std::ios::binary);
|
630
621
|
|
631
622
|
if (!input.is_open())
|
@@ -640,7 +631,7 @@ namespace hnswlib {
|
|
640
631
|
readBinaryPOD(input, max_elements_);
|
641
632
|
readBinaryPOD(input, cur_element_count);
|
642
633
|
|
643
|
-
size_t max_elements=max_elements_i;
|
634
|
+
size_t max_elements = max_elements_i;
|
644
635
|
if(max_elements < cur_element_count)
|
645
636
|
max_elements = max_elements_;
|
646
637
|
max_elements_ = max_elements;
|
@@ -689,26 +680,19 @@ namespace hnswlib {
|
|
689
680
|
|
690
681
|
input.seekg(pos,input.beg);
|
691
682
|
|
692
|
-
|
693
683
|
data_level0_memory_ = (char *) malloc(max_elements * size_data_per_element_);
|
694
684
|
if (data_level0_memory_ == nullptr)
|
695
685
|
throw std::runtime_error("Not enough memory: loadIndex failed to allocate level0");
|
696
686
|
input.read(data_level0_memory_, cur_element_count * size_data_per_element_);
|
697
687
|
|
698
|
-
|
699
|
-
|
700
|
-
|
701
688
|
size_links_per_element_ = maxM_ * sizeof(tableint) + sizeof(linklistsizeint);
|
702
689
|
|
703
|
-
|
704
690
|
size_links_level0_ = maxM0_ * sizeof(tableint) + sizeof(linklistsizeint);
|
705
691
|
std::vector<std::mutex>(max_elements).swap(link_list_locks_);
|
706
692
|
std::vector<std::mutex>(max_update_element_locks).swap(link_list_update_locks_);
|
707
693
|
|
708
|
-
|
709
694
|
visited_list_pool_ = new VisitedListPool(1, max_elements);
|
710
695
|
|
711
|
-
|
712
696
|
linkLists_ = (char **) malloc(sizeof(void *) * max_elements);
|
713
697
|
if (linkLists_ == nullptr)
|
714
698
|
throw std::runtime_error("Not enough memory: loadIndex failed to allocate linklists");
|
@@ -732,11 +716,9 @@ namespace hnswlib {
|
|
732
716
|
}
|
733
717
|
}
|
734
718
|
|
735
|
-
has_deletions_=false;
|
736
|
-
|
737
719
|
for (size_t i = 0; i < cur_element_count; i++) {
|
738
720
|
if(isMarkedDeleted(i))
|
739
|
-
|
721
|
+
num_deleted_ += 1;
|
740
722
|
}
|
741
723
|
|
742
724
|
input.close();
|
@@ -745,7 +727,7 @@ namespace hnswlib {
|
|
745
727
|
}
|
746
728
|
|
747
729
|
template<typename data_t>
|
748
|
-
std::vector<data_t> getDataByLabel(labeltype label)
|
730
|
+
std::vector<data_t> getDataByLabel(labeltype label) const
|
749
731
|
{
|
750
732
|
tableint label_c;
|
751
733
|
auto search = label_lookup_.find(label);
|
@@ -758,7 +740,7 @@ namespace hnswlib {
|
|
758
740
|
size_t dim = *((size_t *) dist_func_param_);
|
759
741
|
std::vector<data_t> data;
|
760
742
|
data_t* data_ptr = (data_t*) data_ptrv;
|
761
|
-
for (
|
743
|
+
for (int i = 0; i < dim; i++) {
|
762
744
|
data.push_back(*data_ptr);
|
763
745
|
data_ptr += 1;
|
764
746
|
}
|
@@ -766,19 +748,19 @@ namespace hnswlib {
|
|
766
748
|
}
|
767
749
|
|
768
750
|
static const unsigned char DELETE_MARK = 0x01;
|
769
|
-
//
|
751
|
+
// static const unsigned char REUSE_MARK = 0x10;
|
770
752
|
/**
|
771
753
|
* Marks an element with the given label deleted, does NOT really change the current graph.
|
772
754
|
* @param label
|
773
755
|
*/
|
774
756
|
void markDelete(labeltype label)
|
775
757
|
{
|
776
|
-
has_deletions_=true;
|
777
758
|
auto search = label_lookup_.find(label);
|
778
759
|
if (search == label_lookup_.end()) {
|
779
760
|
throw std::runtime_error("Label not found");
|
780
761
|
}
|
781
|
-
|
762
|
+
tableint internalId = search->second;
|
763
|
+
markDeletedInternal(internalId);
|
782
764
|
}
|
783
765
|
|
784
766
|
/**
|
@@ -787,8 +769,31 @@ namespace hnswlib {
|
|
787
769
|
* @param internalId
|
788
770
|
*/
|
789
771
|
void markDeletedInternal(tableint internalId) {
|
790
|
-
|
791
|
-
|
772
|
+
assert(internalId < cur_element_count);
|
773
|
+
if (!isMarkedDeleted(internalId))
|
774
|
+
{
|
775
|
+
unsigned char *ll_cur = ((unsigned char *)get_linklist0(internalId))+2;
|
776
|
+
*ll_cur |= DELETE_MARK;
|
777
|
+
num_deleted_ += 1;
|
778
|
+
}
|
779
|
+
else
|
780
|
+
{
|
781
|
+
throw std::runtime_error("The requested to delete element is already deleted");
|
782
|
+
}
|
783
|
+
}
|
784
|
+
|
785
|
+
/**
|
786
|
+
* Remove the deleted mark of the node, does NOT really change the current graph.
|
787
|
+
* @param label
|
788
|
+
*/
|
789
|
+
void unmarkDelete(labeltype label)
|
790
|
+
{
|
791
|
+
auto search = label_lookup_.find(label);
|
792
|
+
if (search == label_lookup_.end()) {
|
793
|
+
throw std::runtime_error("Label not found");
|
794
|
+
}
|
795
|
+
tableint internalId = search->second;
|
796
|
+
unmarkDeletedInternal(internalId);
|
792
797
|
}
|
793
798
|
|
794
799
|
/**
|
@@ -796,8 +801,17 @@ namespace hnswlib {
|
|
796
801
|
* @param internalId
|
797
802
|
*/
|
798
803
|
void unmarkDeletedInternal(tableint internalId) {
|
799
|
-
|
800
|
-
|
804
|
+
assert(internalId < cur_element_count);
|
805
|
+
if (isMarkedDeleted(internalId))
|
806
|
+
{
|
807
|
+
unsigned char *ll_cur = ((unsigned char *)get_linklist0(internalId))+2;
|
808
|
+
*ll_cur &= ~DELETE_MARK;
|
809
|
+
num_deleted_ -= 1;
|
810
|
+
}
|
811
|
+
else
|
812
|
+
{
|
813
|
+
throw std::runtime_error("The requested to undelete element is not deleted");
|
814
|
+
}
|
801
815
|
}
|
802
816
|
|
803
817
|
/**
|
@@ -858,8 +872,8 @@ namespace hnswlib {
|
|
858
872
|
}
|
859
873
|
|
860
874
|
for (auto&& neigh : sNeigh) {
|
861
|
-
//
|
862
|
-
//
|
875
|
+
// if (neigh == internalId)
|
876
|
+
// continue;
|
863
877
|
|
864
878
|
std::priority_queue<std::pair<dist_t, tableint>, std::vector<std::pair<dist_t, tableint>>, CompareByFirst> candidates;
|
865
879
|
size_t size = sCand.find(neigh) == sCand.end() ? sCand.size() : sCand.size() - 1; // sCand guaranteed to have size >= 1
|
@@ -990,7 +1004,6 @@ namespace hnswlib {
|
|
990
1004
|
unmarkDeletedInternal(existingInternalId);
|
991
1005
|
}
|
992
1006
|
updatePoint(data_point, existingInternalId, 1.0);
|
993
|
-
|
994
1007
|
return existingInternalId;
|
995
1008
|
}
|
996
1009
|
|
@@ -1134,7 +1147,7 @@ namespace hnswlib {
|
|
1134
1147
|
}
|
1135
1148
|
|
1136
1149
|
std::priority_queue<std::pair<dist_t, tableint>, std::vector<std::pair<dist_t, tableint>>, CompareByFirst> top_candidates;
|
1137
|
-
if (
|
1150
|
+
if (num_deleted_) {
|
1138
1151
|
top_candidates=searchBaseLayerST<true,true>(
|
1139
1152
|
currObj, query_data, std::max(ef_, k));
|
1140
1153
|
}
|
data/ext/hnswlib/src/hnswlib.h
CHANGED
@@ -4,6 +4,9 @@
|
|
4
4
|
#define USE_SSE
|
5
5
|
#ifdef __AVX__
|
6
6
|
#define USE_AVX
|
7
|
+
#ifdef __AVX512F__
|
8
|
+
#define USE_AVX512
|
9
|
+
#endif
|
7
10
|
#endif
|
8
11
|
#endif
|
9
12
|
#endif
|
@@ -16,10 +19,16 @@
|
|
16
19
|
#include <x86intrin.h>
|
17
20
|
#endif
|
18
21
|
|
22
|
+
#if defined(USE_AVX512)
|
23
|
+
#include <immintrin.h>
|
24
|
+
#endif
|
25
|
+
|
19
26
|
#if defined(__GNUC__)
|
20
27
|
#define PORTABLE_ALIGN32 __attribute__((aligned(32)))
|
28
|
+
#define PORTABLE_ALIGN64 __attribute__((aligned(64)))
|
21
29
|
#else
|
22
30
|
#define PORTABLE_ALIGN32 __declspec(align(32))
|
31
|
+
#define PORTABLE_ALIGN64 __declspec(align(64))
|
23
32
|
#endif
|
24
33
|
#endif
|
25
34
|
|
data/ext/hnswlib/src/space_ip.h
CHANGED
@@ -124,7 +124,40 @@ namespace hnswlib {
|
|
124
124
|
|
125
125
|
#endif
|
126
126
|
|
127
|
-
|
127
|
+
|
128
|
+
#if defined(USE_AVX512)
|
129
|
+
|
130
|
+
static float
|
131
|
+
InnerProductSIMD16Ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
|
132
|
+
float PORTABLE_ALIGN64 TmpRes[16];
|
133
|
+
float *pVect1 = (float *) pVect1v;
|
134
|
+
float *pVect2 = (float *) pVect2v;
|
135
|
+
size_t qty = *((size_t *) qty_ptr);
|
136
|
+
|
137
|
+
size_t qty16 = qty / 16;
|
138
|
+
|
139
|
+
|
140
|
+
const float *pEnd1 = pVect1 + 16 * qty16;
|
141
|
+
|
142
|
+
__m512 sum512 = _mm512_set1_ps(0);
|
143
|
+
|
144
|
+
while (pVect1 < pEnd1) {
|
145
|
+
//_mm_prefetch((char*)(pVect2 + 16), _MM_HINT_T0);
|
146
|
+
|
147
|
+
__m512 v1 = _mm512_loadu_ps(pVect1);
|
148
|
+
pVect1 += 16;
|
149
|
+
__m512 v2 = _mm512_loadu_ps(pVect2);
|
150
|
+
pVect2 += 16;
|
151
|
+
sum512 = _mm512_add_ps(sum512, _mm512_mul_ps(v1, v2));
|
152
|
+
}
|
153
|
+
|
154
|
+
_mm512_store_ps(TmpRes, sum512);
|
155
|
+
float sum = TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] + TmpRes[7] + TmpRes[8] + TmpRes[9] + TmpRes[10] + TmpRes[11] + TmpRes[12] + TmpRes[13] + TmpRes[14] + TmpRes[15];
|
156
|
+
|
157
|
+
return 1.0f - sum;
|
158
|
+
}
|
159
|
+
|
160
|
+
#elif defined(USE_AVX)
|
128
161
|
|
129
162
|
static float
|
130
163
|
InnerProductSIMD16Ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
|
@@ -211,7 +244,7 @@ namespace hnswlib {
|
|
211
244
|
|
212
245
|
#endif
|
213
246
|
|
214
|
-
#if defined(USE_SSE) || defined(USE_AVX)
|
247
|
+
#if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
|
215
248
|
static float
|
216
249
|
InnerProductSIMD16ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
|
217
250
|
size_t qty = *((size_t *) qty_ptr);
|
@@ -250,7 +283,7 @@ namespace hnswlib {
|
|
250
283
|
InnerProductSpace() : data_size_(0), dim_(0) { }
|
251
284
|
InnerProductSpace(size_t dim) {
|
252
285
|
fstdistfunc_ = InnerProduct;
|
253
|
-
#if defined(USE_AVX) || defined(USE_SSE)
|
286
|
+
#if defined(USE_AVX) || defined(USE_SSE) || defined(USE_AVX512)
|
254
287
|
if (dim % 16 == 0)
|
255
288
|
fstdistfunc_ = InnerProductSIMD16Ext;
|
256
289
|
else if (dim % 4 == 0)
|
data/ext/hnswlib/src/space_l2.h
CHANGED
@@ -19,7 +19,41 @@ namespace hnswlib {
|
|
19
19
|
return (res);
|
20
20
|
}
|
21
21
|
|
22
|
-
#if defined(
|
22
|
+
#if defined(USE_AVX512)
|
23
|
+
|
24
|
+
// Favor using AVX512 if available.
|
25
|
+
static float
|
26
|
+
L2SqrSIMD16Ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
|
27
|
+
float *pVect1 = (float *) pVect1v;
|
28
|
+
float *pVect2 = (float *) pVect2v;
|
29
|
+
size_t qty = *((size_t *) qty_ptr);
|
30
|
+
float PORTABLE_ALIGN64 TmpRes[16];
|
31
|
+
size_t qty16 = qty >> 4;
|
32
|
+
|
33
|
+
const float *pEnd1 = pVect1 + (qty16 << 4);
|
34
|
+
|
35
|
+
__m512 diff, v1, v2;
|
36
|
+
__m512 sum = _mm512_set1_ps(0);
|
37
|
+
|
38
|
+
while (pVect1 < pEnd1) {
|
39
|
+
v1 = _mm512_loadu_ps(pVect1);
|
40
|
+
pVect1 += 16;
|
41
|
+
v2 = _mm512_loadu_ps(pVect2);
|
42
|
+
pVect2 += 16;
|
43
|
+
diff = _mm512_sub_ps(v1, v2);
|
44
|
+
// sum = _mm512_fmadd_ps(diff, diff, sum);
|
45
|
+
sum = _mm512_add_ps(sum, _mm512_mul_ps(diff, diff));
|
46
|
+
}
|
47
|
+
|
48
|
+
_mm512_store_ps(TmpRes, sum);
|
49
|
+
float res = TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] +
|
50
|
+
TmpRes[7] + TmpRes[8] + TmpRes[9] + TmpRes[10] + TmpRes[11] + TmpRes[12] +
|
51
|
+
TmpRes[13] + TmpRes[14] + TmpRes[15];
|
52
|
+
|
53
|
+
return (res);
|
54
|
+
}
|
55
|
+
|
56
|
+
#elif defined(USE_AVX)
|
23
57
|
|
24
58
|
// Favor using AVX if available.
|
25
59
|
static float
|
@@ -106,7 +140,7 @@ namespace hnswlib {
|
|
106
140
|
}
|
107
141
|
#endif
|
108
142
|
|
109
|
-
#if defined(USE_SSE) || defined(USE_AVX)
|
143
|
+
#if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
|
110
144
|
static float
|
111
145
|
L2SqrSIMD16ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
|
112
146
|
size_t qty = *((size_t *) qty_ptr);
|
@@ -175,7 +209,7 @@ namespace hnswlib {
|
|
175
209
|
L2Space() : data_size_(0), dim_(0) { }
|
176
210
|
L2Space(size_t dim) {
|
177
211
|
fstdistfunc_ = L2Sqr;
|
178
|
-
#if defined(USE_SSE) || defined(USE_AVX)
|
212
|
+
#if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
|
179
213
|
if (dim % 16 == 0)
|
180
214
|
fstdistfunc_ = L2SqrSIMD16Ext;
|
181
215
|
else if (dim % 4 == 0)
|
@@ -279,4 +313,4 @@ namespace hnswlib {
|
|
279
313
|
};
|
280
314
|
|
281
315
|
|
282
|
-
}
|
316
|
+
}
|
data/lib/hnswlib/version.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
# Hnswlib.rb provides Ruby bindings for the Hnswlib.
|
4
4
|
module Hnswlib
|
5
5
|
# The version of Hnswlib.rb you install.
|
6
|
-
VERSION = '0.
|
6
|
+
VERSION = '0.5.0'
|
7
7
|
|
8
8
|
# The version of Hnswlib included with gem.
|
9
|
-
HSWLIB_VERSION = '0.
|
9
|
+
HSWLIB_VERSION = '0.6.0'
|
10
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hnswlib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshoku
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Hnswlib.rb provides Ruby bindings for the Hnswlib.
|
14
14
|
email:
|
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '0'
|
66
66
|
requirements: []
|
67
|
-
rubygems_version: 3.2.
|
67
|
+
rubygems_version: 3.2.32
|
68
68
|
signing_key:
|
69
69
|
specification_version: 4
|
70
70
|
summary: Ruby bindings for the Hnswlib.
|