vearch / vearch

Distributed vector search for AI-native applications

Home Page:https://vearch.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

请问hnsw索引的增删改与search是可以并发的吗?

yockie opened this issue · comments

阅读了向量引擎gamma的代码,理解增删改三者之间是可以并发的(有锁互斥);但是增删改与search是不能并发的?

原因是searchKnn中遍历节点的邻居列表时都没有加锁(get_linklist),如下面截图,不知道我理解的对不对?

image

image

所有写串行,读并行,读写之间不影响

所有写串行,读并行,读写之间不影响

例如上面第一个截图红框的部分,这里读线程调用get_linklist是没有锁保护的,即拿到currObj节点在第level层的邻居列表长度和指针:data、size都是没有锁保护的;

如果此时另外一个写线程正在Update,在updatePoint函数中会对已有节点的邻居列表进行重新设置,如下图;假如此时修改了上面的curObj节点的邻居列表长度(由于getNeighborsByHeuristic2中重新选择邻居可能会改变邻居的个数),那么上面读线程遍历按老的size遍历data是不是不安全的?

image

改变邻居的个数但是不影响邻居节点的存储,邻居节点的存储是nlinks个节点的数组,这个数组是不变的。即update的过程中,search线程可能读的邻居节点数据不是实时的,但是不会越界

@zcdb @gyd-a 感谢大佬回复,这块能理解了;

由于删除是标记删除,如果增删的频率很高,hnsw索引的内存应该是会膨胀的;请问现在是如何解决由于节点增删引起的hnsw索引内存膨胀问题的?

这种情况可能重建索引更合适,如果增删的频率很高

@zcdb @gyd-a 因为在GammaIndexHNSWLIB中保证了所有写操作是串行进行的,那么HierarchicalNSW中的link_list_locks_是不是就不需要了,我理解link_list_locks_是原先hnswlib为了安全的并发写操作加的锁吧

另外,addPoint时为啥不把embedding数据拷贝到对应内存空间啊?见下面的红框部分,找了一下hnsw其他地方没有拷贝data_point的地方

image

另外,addPoint时为啥不把embedding数据拷贝到对应内存空间啊?见下面的红框部分,找了一下hnsw其他地方没有拷贝data_point的地方

image

向量是由GammaIndexHNSWLIB管理的,并没有使用hnswlib这部分的结构

另外,addPoint时为啥不把embedding数据拷贝到对应内存空间啊?见下面的红框部分,找了一下hnsw其他地方没有拷贝data_point的地方
image

向量是由GammaIndexHNSWLIB管理的,并没有使用hnswlib这部分的结构

我知道是用GammaIndexHNSWLIB中的raw_vec_保存向量的,getDataByInternalId是一个虚函数,由GammaIndexHNSWLIB实现,从raw_vec_找到对应位置的向量首地址;但是我从GammaIndexHNSWLIB::Add函数一路跟下来,没看到有代码插入到raw_vec_中,求指教

commented

另外,addPoint时为啥不把embedding数据拷贝到对应内存空间啊?见下面的红框部分,找了一下hnsw其他地方没有拷贝data_point的地方
image

向量是由GammaIndexHNSWLIB管理的,并没有使用hnswlib这部分的结构

我知道是用GammaIndexHNSWLIB中的raw_vec_保存向量的,getDataByInternalId是一个虚函数,由GammaIndexHNSWLIB实现,从raw_vec_找到对应位置的向量首地址;但是我从GammaIndexHNSWLIB::Add函数一路跟下来,没看到有代码插入到raw_vec_中,求指教

是向量先插入到raw_rec,然后hnsw索引再去对对应的向量构建索引。可以看看vectormanager的实现

@zcdb @gyd-a 因为在GammaIndexHNSWLIB中保证了所有写操作是串行进行的,那么HierarchicalNSW中的link_list_locks_是不是就不需要了,我理解link_list_locks_是原先hnswlib为了安全的并发写操作加的锁吧

@zcdb 大佬,请教一下这个问题

commented

@zcdb @gyd-a 因为在GammaIndexHNSWLIB中保证了所有写操作是串行进行的,那么HierarchicalNSW中的link_list_locks_是不是就不需要了,我理解link_list_locks_是原先hnswlib为了安全的并发写操作加的锁吧

@zcdb 大佬,请教一下这个问题

hnsw是支持批量写的,同时对多条数据构建索引需要这个锁的