mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-11 07:06:57 +08:00
13
src/hnsw.h
13
src/hnsw.h
@@ -445,4 +445,17 @@ typedef struct PointerHashEntry
|
|||||||
#define SH_DECLARE
|
#define SH_DECLARE
|
||||||
#include "lib/simplehash.h"
|
#include "lib/simplehash.h"
|
||||||
|
|
||||||
|
typedef struct OffsetHashEntry
|
||||||
|
{
|
||||||
|
Size offset;
|
||||||
|
char status;
|
||||||
|
} OffsetHashEntry;
|
||||||
|
|
||||||
|
#define SH_PREFIX offsethash
|
||||||
|
#define SH_ELEMENT_TYPE OffsetHashEntry
|
||||||
|
#define SH_KEY_TYPE Size
|
||||||
|
#define SH_SCOPE extern
|
||||||
|
#define SH_DECLARE
|
||||||
|
#include "lib/simplehash.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -81,9 +81,31 @@ hash_pointer(uintptr_t ptr)
|
|||||||
#define SH_DEFINE
|
#define SH_DEFINE
|
||||||
#include "lib/simplehash.h"
|
#include "lib/simplehash.h"
|
||||||
|
|
||||||
|
/* Offset hash table */
|
||||||
|
static uint32
|
||||||
|
hash_offset(Size offset)
|
||||||
|
{
|
||||||
|
#if SIZEOF_SIZE_T == 8
|
||||||
|
return murmurhash64((uint64) offset);
|
||||||
|
#else
|
||||||
|
return murmurhash32((uint32) offset);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SH_PREFIX offsethash
|
||||||
|
#define SH_ELEMENT_TYPE OffsetHashEntry
|
||||||
|
#define SH_KEY_TYPE Size
|
||||||
|
#define SH_KEY offset
|
||||||
|
#define SH_HASH_KEY(tb, key) hash_offset(key)
|
||||||
|
#define SH_EQUAL(tb, a, b) (a == b)
|
||||||
|
#define SH_SCOPE extern
|
||||||
|
#define SH_DEFINE
|
||||||
|
#include "lib/simplehash.h"
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
pointerhash_hash *pointers;
|
pointerhash_hash *pointers;
|
||||||
|
offsethash_hash *offsets;
|
||||||
tidhash_hash *tids;
|
tidhash_hash *tids;
|
||||||
} visited_hash;
|
} visited_hash;
|
||||||
|
|
||||||
@@ -636,6 +658,8 @@ InitVisited(char *base, visited_hash * v, Relation index, int ef, int m)
|
|||||||
{
|
{
|
||||||
if (index != NULL)
|
if (index != NULL)
|
||||||
v->tids = tidhash_create(CurrentMemoryContext, ef * m * 2, NULL);
|
v->tids = tidhash_create(CurrentMemoryContext, ef * m * 2, NULL);
|
||||||
|
else if (base != NULL)
|
||||||
|
v->offsets = offsethash_create(CurrentMemoryContext, ef * m * 2, NULL);
|
||||||
else
|
else
|
||||||
v->pointers = pointerhash_create(CurrentMemoryContext, ef * m * 2, NULL);
|
v->pointers = pointerhash_create(CurrentMemoryContext, ef * m * 2, NULL);
|
||||||
}
|
}
|
||||||
@@ -644,21 +668,34 @@ InitVisited(char *base, visited_hash * v, Relation index, int ef, int m)
|
|||||||
* Add to visited
|
* Add to visited
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
AddToVisited(char *base, visited_hash * v, HnswElement element, Relation index, bool *found)
|
AddToVisited(char *base, visited_hash * v, HnswCandidate * hc, Relation index, bool *found)
|
||||||
{
|
{
|
||||||
if (index != NULL)
|
if (index != NULL)
|
||||||
{
|
{
|
||||||
|
HnswElement element = HnswPtrAccess(base, hc->element);
|
||||||
ItemPointerData indextid;
|
ItemPointerData indextid;
|
||||||
|
|
||||||
ItemPointerSet(&indextid, element->blkno, element->offno);
|
ItemPointerSet(&indextid, element->blkno, element->offno);
|
||||||
tidhash_insert(v->tids, indextid, found);
|
tidhash_insert(v->tids, indextid, found);
|
||||||
}
|
}
|
||||||
|
else if (base != NULL)
|
||||||
|
{
|
||||||
|
#if PG_VERSION_NUM >= 130000
|
||||||
|
HnswElement element = HnswPtrAccess(base, hc->element);
|
||||||
|
|
||||||
|
offsethash_insert_hash(v->offsets, HnswPtrOffset(hc->element), element->hash, found);
|
||||||
|
#else
|
||||||
|
offsethash_insert(v->offsets, HnswPtrOffset(hc->element), found);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if PG_VERSION_NUM >= 130000
|
#if PG_VERSION_NUM >= 130000
|
||||||
pointerhash_insert_hash(v->pointers, (uintptr_t) element, element->hash, found);
|
HnswElement element = HnswPtrAccess(base, hc->element);
|
||||||
|
|
||||||
|
pointerhash_insert_hash(v->pointers, (uintptr_t) HnswPtrPointer(hc->element), element->hash, found);
|
||||||
#else
|
#else
|
||||||
pointerhash_insert(v->pointers, (uintptr_t) element, found);
|
pointerhash_insert(v->pointers, (uintptr_t) HnswPtrPointer(hc->element), found);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +748,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
AddToVisited(base, &v, HnswPtrAccess(base, hc->element), index, &found);
|
AddToVisited(base, &v, hc, index, &found);
|
||||||
|
|
||||||
pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node));
|
pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node));
|
||||||
pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node));
|
pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node));
|
||||||
@@ -755,14 +792,14 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
for (int i = 0; i < neighborhood->length; i++)
|
for (int i = 0; i < neighborhood->length; i++)
|
||||||
{
|
{
|
||||||
HnswCandidate *e = &neighborhood->items[i];
|
HnswCandidate *e = &neighborhood->items[i];
|
||||||
HnswElement eElement = HnswPtrAccess(base, e->element);
|
|
||||||
bool visited;
|
bool visited;
|
||||||
|
|
||||||
AddToVisited(base, &v, eElement, index, &visited);
|
AddToVisited(base, &v, e, index, &visited);
|
||||||
|
|
||||||
if (!visited)
|
if (!visited)
|
||||||
{
|
{
|
||||||
float eDistance;
|
float eDistance;
|
||||||
|
HnswElement eElement = HnswPtrAccess(base, e->element);
|
||||||
|
|
||||||
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
||||||
|
|
||||||
@@ -1143,7 +1180,14 @@ RemoveElements(char *base, List *w, HnswElement skipElement)
|
|||||||
static void
|
static void
|
||||||
PrecomputeHash(char *base, HnswElement element)
|
PrecomputeHash(char *base, HnswElement element)
|
||||||
{
|
{
|
||||||
element->hash = hash_pointer((uintptr_t) element);
|
HnswElementPtr ptr;
|
||||||
|
|
||||||
|
HnswPtrStore(base, ptr, element);
|
||||||
|
|
||||||
|
if (base == NULL)
|
||||||
|
element->hash = hash_pointer((uintptr_t) HnswPtrPointer(ptr));
|
||||||
|
else
|
||||||
|
element->hash = hash_offset(HnswPtrOffset(ptr));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user