Skip to content

Commit 212cba1

Browse files
committed
🔨 version 1.0.4 - Add UpdatePoint, UpdateBatchPoints APIs
1 parent be02fde commit 212cba1

6 files changed

Lines changed: 47 additions & 16 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Hnswlib to go. Golang interface to hnswlib(https://github.com/nmslib/hnswlib). T
66

77
### Version
88

9+
* version 1.0.4
10+
* Add `UpdatePoint`, `UpdateBatchPoints` APIs
11+
912
* version 1.0.3
1013
* Add `GetMaxElements`, `GetCurrentElementCount`, `GetDeleteCount`, `GetVectorByLabel` APIs
1114

hnsw.go

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bool resizeIndex(HNSW index, unsigned long int new_max_elements);
1818
bool markDelete(HNSW index, unsigned long int label);
1919
bool unmarkDelete(HNSW index, unsigned long int label);
2020
bool isMarkedDeleted(HNSW index, unsigned long int label);
21-
bool updatePoint(HNSW index, float *vec, unsigned long int label);
21+
bool updatePoint(HNSW index, float *vec, unsigned long int label, float updateNeighborProbability);
2222
2323
void getDataByLabel(HNSW index, unsigned long int label, float* out_data);
2424
*/
@@ -30,13 +30,6 @@ import (
3030
"unsafe"
3131
)
3232

33-
func toSlice(v *C.float, len int) []float32 {
34-
// 创建一个指向C数组的slice
35-
slice := (*[1 << 30]float32)(unsafe.Pointer(v))[:len:len]
36-
// 复制slice的值,将其转换为一个新的Go切片
37-
return append([]float32(nil), slice...)
38-
}
39-
4033
type HNSW struct {
4134
index C.HNSW
4235
spaceType string
@@ -79,7 +72,7 @@ func Load(location string, dim int, spaceType string) *HNSW {
7972
return &hnsw
8073
}
8174

82-
// Unload TODO Test for release the graph memory
75+
// Unload release the graph memory
8376
func (h *HNSW) Unload() bool {
8477
if h.index == nil {
8578
return false
@@ -129,7 +122,7 @@ func (h *HNSW) AddPoint(vector []float32, label uint32) bool {
129122

130123
// AddBatchPoints add some points on graph with goroutine
131124
func (h *HNSW) AddBatchPoints(vectors [][]float32, labels []uint32, coroutines int) bool {
132-
if len(vectors) != len(labels) {
125+
if len(vectors) != len(labels) || coroutines < 1 {
133126
return false
134127
}
135128

@@ -174,7 +167,12 @@ func (h *HNSW) SearchKNN(vector []float32, N int) ([]uint32, []float32) {
174167
return labels[:numResult], dists[:numResult]
175168
}
176169

170+
// SearchBatchKNN search multiple points on graph with knn-algorithm
177171
func (h *HNSW) SearchBatchKNN(vectors [][]float32, N, coroutines int) ([][]uint32, [][]float32) {
172+
if coroutines < 1 {
173+
coroutines = 1
174+
}
175+
178176
var lock sync.Mutex
179177
labelList := make([][]uint32, len(vectors))
180178
distList := make([][]float32, len(vectors))
@@ -240,6 +238,39 @@ func (h *HNSW) GetLabelIsMarkedDeleted(label uint32) bool {
240238
return isDelete
241239
}
242240

241+
// UpdatePoint update point on graph
242+
func (h *HNSW) UpdatePoint(vector []float32, label uint32, updateNeighborProbability float32) bool {
243+
isUpdate := bool(C.updatePoint(h.index, (*C.float)(unsafe.Pointer(&vector[0])), C.ulong(label), C.float(updateNeighborProbability)))
244+
return isUpdate
245+
}
246+
247+
// UpdateBatchPoints update points on graph
248+
func (h *HNSW) UpdateBatchPoints(vectors [][]float32, labels []uint32, updateNeighborProbabilities []float32, coroutines int) bool {
249+
if len(vectors) != len(labels) && len(labels) != len(updateNeighborProbabilities) || coroutines < 1 {
250+
return false
251+
}
252+
253+
b := len(vectors) / coroutines
254+
var wg sync.WaitGroup
255+
for i := 0; i < coroutines; i++ {
256+
wg.Add(1)
257+
258+
end := (i + 1) * b
259+
if i == coroutines-1 && len(vectors) > end {
260+
end = len(vectors)
261+
}
262+
go func(thisVectors [][]float32, thisLabels []uint32, thisProb []float32) {
263+
defer wg.Done()
264+
for j := 0; j < len(thisVectors); j++ {
265+
h.UpdatePoint(thisVectors[j], thisLabels[j], thisProb[j])
266+
}
267+
}(vectors[i*b:end], labels[i*b:end], updateNeighborProbabilities[i*b:end])
268+
}
269+
270+
wg.Wait()
271+
return true
272+
}
273+
243274
// GetMaxElements get index max elements
244275
func (h *HNSW) GetMaxElements() int {
245276
maxElements := int(C.getMaxElements(h.index))

hnsw_wrapper.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ bool isMarkedDeleted(HNSW index, unsigned long int label) {
104104
return false;
105105
}
106106

107-
bool updatePoint(HNSW index, float *vec, unsigned long int label) {
107+
bool updatePoint(HNSW index, float *vec, unsigned long int label, float updateNeighborProbability) {
108108
std::unique_lock <std::mutex> lock_table(((hnswlib::HierarchicalNSW<float> *) index)->label_lookup_lock);
109109
auto search = ((hnswlib::HierarchicalNSW<float> *) index)->label_lookup_.find(label);
110110

111111
if (search != ((hnswlib::HierarchicalNSW<float> *) index)->label_lookup_.end()) {
112112
hnswlib::tableint existingInternalId = search->second;
113113
lock_table.unlock();
114114
// const void *dataPoint, tableint internalId, float updateNeighborProbability
115-
((hnswlib::HierarchicalNSW<float> *) index)->updatePoint(vec, existingInternalId, 1.0);
115+
((hnswlib::HierarchicalNSW<float> *) index)->updatePoint(vec, existingInternalId, updateNeighborProbability);
116116
return true;
117117
}
118118
return false;
@@ -121,9 +121,6 @@ bool updatePoint(HNSW index, float *vec, unsigned long int label) {
121121
void getDataByLabel(HNSW index, unsigned long int label, float* out_data) {
122122
auto data = ((hnswlib::HierarchicalNSW<float>*)index)->getDataByLabel<float>(label);
123123
std::vector<float>* vec = new std::vector<float>(data.begin(), data.end());
124-
if (vec == nullptr) {
125-
return;
126-
}
127124

128125
size_t size = vec->size();
129126
for (size_t i = 0; i < size; i++) {

hnsw_wrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ bool unmarkDelete(HNSW index, unsigned long int label);
2424

2525
bool isMarkedDeleted(HNSW index, unsigned long int label);
2626

27-
bool updatePoint(HNSW index, float *vec, unsigned long int label);
27+
bool updatePoint(HNSW index, float *vec, unsigned long int label, float updateNeighborProbability);
2828

2929
int getMaxElements(HNSW index);
3030

hnsw_wrapper.o

8 Bytes
Binary file not shown.

libhnsw.a

8 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)