mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-11 23:26:55 +08:00
Eliminate a few HnswPtrAccess invocations
HnswPtrAccess() is pretty cheap, but it stills seems worthwhile to avoid repeated calls in the hot paths when it can be easily avoided.
This commit is contained in:
@@ -559,13 +559,12 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the distance for a candidate
|
* Get the distance between 'hc' and 'q'
|
||||||
*/
|
*/
|
||||||
static float
|
static float
|
||||||
GetCandidateDistance(char *base, HnswCandidate * hc, Datum q, FmgrInfo *procinfo, Oid collation)
|
GetElementDistance(char *base, HnswElement hc, Datum q, FmgrInfo *procinfo, Oid collation)
|
||||||
{
|
{
|
||||||
HnswElement hce = HnswPtrAccess(base, hc->element);
|
Datum value = HnswGetValue(base, hc);
|
||||||
Datum value = HnswGetValue(base, hce);
|
|
||||||
|
|
||||||
return DatumGetFloat8(FunctionCall2Coll(procinfo, collation, q, value));
|
return DatumGetFloat8(FunctionCall2Coll(procinfo, collation, q, value));
|
||||||
}
|
}
|
||||||
@@ -580,7 +579,7 @@ HnswEntryCandidate(char *base, HnswElement entryPoint, Datum q, Relation index,
|
|||||||
|
|
||||||
HnswPtrStore(base, hc->element, entryPoint);
|
HnswPtrStore(base, hc->element, entryPoint);
|
||||||
if (index == NULL)
|
if (index == NULL)
|
||||||
hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation);
|
hc->distance = GetElementDistance(base, entryPoint, q, procinfo, collation);
|
||||||
else
|
else
|
||||||
HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec);
|
HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec);
|
||||||
return hc;
|
return hc;
|
||||||
@@ -667,17 +666,14 @@ AddToVisited(char *base, visited_hash * v, HnswElement element, Relation index,
|
|||||||
* Count element towards ef
|
* Count element towards ef
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
CountElement(char *base, HnswElement skipElement, HnswCandidate * hc)
|
CountElement(char *base, HnswElement skipElement, HnswElement e)
|
||||||
{
|
{
|
||||||
HnswElement e;
|
|
||||||
|
|
||||||
if (skipElement == NULL)
|
if (skipElement == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Ensure does not access heaptidsLength during in-memory build */
|
/* Ensure does not access heaptidsLength during in-memory build */
|
||||||
pg_memory_barrier();
|
pg_memory_barrier();
|
||||||
|
|
||||||
e = HnswPtrAccess(base, hc->element);
|
|
||||||
return e->heaptidsLength != 0;
|
return e->heaptidsLength != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,9 +705,10 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
foreach(lc2, ep)
|
foreach(lc2, ep)
|
||||||
{
|
{
|
||||||
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
||||||
|
HnswElement e = HnswPtrAccess(base, hc->element);
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
AddToVisited(base, &v, HnswPtrAccess(base, hc->element), index, &found);
|
AddToVisited(base, &v, e, 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));
|
||||||
@@ -721,7 +718,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
* would be ideal to do this for inserts as well, but this could
|
* would be ideal to do this for inserts as well, but this could
|
||||||
* affect insert performance.
|
* affect insert performance.
|
||||||
*/
|
*/
|
||||||
if (CountElement(base, skipElement, hc))
|
if (CountElement(base, skipElement, e))
|
||||||
wlen++;
|
wlen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,8 +751,8 @@ 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 *hc = &neighborhood->items[i];
|
||||||
HnswElement eElement = HnswPtrAccess(base, e->element);
|
HnswElement eElement = HnswPtrAccess(base, hc->element);
|
||||||
bool visited;
|
bool visited;
|
||||||
|
|
||||||
AddToVisited(base, &v, eElement, index, &visited);
|
AddToVisited(base, &v, eElement, index, &visited);
|
||||||
@@ -767,7 +764,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
||||||
|
|
||||||
if (index == NULL)
|
if (index == NULL)
|
||||||
eDistance = GetCandidateDistance(base, e, q, procinfo, collation);
|
eDistance = GetElementDistance(base, eElement, q, procinfo, collation);
|
||||||
else
|
else
|
||||||
HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting);
|
HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting);
|
||||||
|
|
||||||
@@ -782,7 +779,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
/* Copy e */
|
/* Copy e */
|
||||||
HnswCandidate *ec = palloc(sizeof(HnswCandidate));
|
HnswCandidate *ec = palloc(sizeof(HnswCandidate));
|
||||||
|
|
||||||
HnswPtrStore(base, ec->element, eElement);
|
ec->element = hc->element;
|
||||||
ec->distance = eDistance;
|
ec->distance = eDistance;
|
||||||
|
|
||||||
pairingheap_add(C, &(CreatePairingHeapNode(ec)->ph_node));
|
pairingheap_add(C, &(CreatePairingHeapNode(ec)->ph_node));
|
||||||
@@ -793,7 +790,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
|||||||
* vacuuming. It would be ideal to do this for inserts as
|
* vacuuming. It would be ideal to do this for inserts as
|
||||||
* well, but this could affect insert performance.
|
* well, but this could affect insert performance.
|
||||||
*/
|
*/
|
||||||
if (CountElement(base, skipElement, e))
|
if (CountElement(base, skipElement, eElement))
|
||||||
{
|
{
|
||||||
wlen++;
|
wlen++;
|
||||||
|
|
||||||
@@ -874,15 +871,12 @@ CompareCandidateDistancesOffset(const void *a, const void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the distance between elements
|
* Calculate the distance between two vectors
|
||||||
*/
|
*/
|
||||||
static float
|
static float
|
||||||
HnswGetDistance(char *base, HnswElement a, HnswElement b, FmgrInfo *procinfo, Oid collation)
|
HnswGetDistance(Datum a, Datum b, FmgrInfo *procinfo, Oid collation)
|
||||||
{
|
{
|
||||||
Datum aValue = HnswGetValue(base, a);
|
return DatumGetFloat8(FunctionCall2Coll(procinfo, collation, a, b));
|
||||||
Datum bValue = HnswGetValue(base, b);
|
|
||||||
|
|
||||||
return DatumGetFloat8(FunctionCall2Coll(procinfo, collation, aValue, bValue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -892,13 +886,15 @@ static bool
|
|||||||
CheckElementCloser(char *base, HnswCandidate * e, List *r, FmgrInfo *procinfo, Oid collation)
|
CheckElementCloser(char *base, HnswCandidate * e, List *r, FmgrInfo *procinfo, Oid collation)
|
||||||
{
|
{
|
||||||
HnswElement eElement = HnswPtrAccess(base, e->element);
|
HnswElement eElement = HnswPtrAccess(base, e->element);
|
||||||
|
Datum eValue = HnswGetValue(base, eElement);
|
||||||
ListCell *lc2;
|
ListCell *lc2;
|
||||||
|
|
||||||
foreach(lc2, r)
|
foreach(lc2, r)
|
||||||
{
|
{
|
||||||
HnswCandidate *ri = lfirst(lc2);
|
HnswCandidate *ri = lfirst(lc2);
|
||||||
HnswElement riElement = HnswPtrAccess(base, ri->element);
|
HnswElement riElement = HnswPtrAccess(base, ri->element);
|
||||||
float distance = HnswGetDistance(base, eElement, riElement, procinfo, collation);
|
Datum riValue = HnswGetValue(base, riElement);
|
||||||
|
float distance = HnswGetDistance(eValue, riValue, procinfo, collation);
|
||||||
|
|
||||||
if (distance <= e->distance)
|
if (distance <= e->distance)
|
||||||
return false;
|
return false;
|
||||||
@@ -1064,7 +1060,7 @@ HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm
|
|||||||
if (HnswPtrIsNull(base, hc3Element->value))
|
if (HnswPtrIsNull(base, hc3Element->value))
|
||||||
HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true);
|
HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true);
|
||||||
else
|
else
|
||||||
hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation);
|
hc3->distance = GetElementDistance(base, hc3Element, q, procinfo, collation);
|
||||||
|
|
||||||
/* Prune element if being deleted */
|
/* Prune element if being deleted */
|
||||||
if (hc3Element->heaptidsLength == 0)
|
if (hc3Element->heaptidsLength == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user