Compare commits

..

2 Commits

Author SHA1 Message Date
Andrew Kane
abbc1c3379 Improved code 2024-03-11 17:30:27 -07:00
Andrew Kane
72c20fc14f Improved performance of parallel HNSW index builds 2024-03-11 17:24:42 -07:00
4 changed files with 27 additions and 43 deletions

View File

@@ -1,3 +1,7 @@
## 0.6.2 (unreleased)
- Improved performance of parallel HNSW index builds
## 0.6.1 (2024-03-04) ## 0.6.1 (2024-03-04)
- Fixed error with `ANALYZE` and vectors with different dimensions - Fixed error with `ANALYZE` and vectors with different dimensions

View File

@@ -17,10 +17,7 @@
#endif #endif
int hnsw_ef_search; int hnsw_ef_search;
int hnsw_entry_lock_tranche_id; int hnsw_lock_tranche_id;
int hnsw_allocator_lock_tranche_id;
int hnsw_flush_lock_tranche_id;
int hnsw_element_lock_tranche_id;
static relopt_kind hnsw_relopt_kind; static relopt_kind hnsw_relopt_kind;
/* /*
@@ -39,27 +36,16 @@ HnswInitLockTranche(void)
bool found; bool found;
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
tranche_ids = ShmemInitStruct("hnsw LWLock ids v2", tranche_ids = ShmemInitStruct("hnsw LWLock ids",
sizeof(int) * 4, sizeof(int) * 1,
&found); &found);
if (!found) if (!found)
{
tranche_ids[0] = LWLockNewTrancheId(); tranche_ids[0] = LWLockNewTrancheId();
tranche_ids[1] = LWLockNewTrancheId(); hnsw_lock_tranche_id = tranche_ids[0];
tranche_ids[2] = LWLockNewTrancheId();
tranche_ids[3] = LWLockNewTrancheId();
}
hnsw_entry_lock_tranche_id = tranche_ids[0];
hnsw_allocator_lock_tranche_id = tranche_ids[1];
hnsw_flush_lock_tranche_id = tranche_ids[2];
hnsw_element_lock_tranche_id = tranche_ids[3];
LWLockRelease(AddinShmemInitLock); LWLockRelease(AddinShmemInitLock);
/* Per-backend registration of the tranche ID */ /* Per-backend registration of the tranche ID */
LWLockRegisterTranche(hnsw_entry_lock_tranche_id, "HnswEntry"); LWLockRegisterTranche(hnsw_lock_tranche_id, "HnswBuild");
LWLockRegisterTranche(hnsw_allocator_lock_tranche_id, "HnswAllocator");
LWLockRegisterTranche(hnsw_flush_lock_tranche_id, "HnswFlush");
LWLockRegisterTranche(hnsw_element_lock_tranche_id, "HnswElement");
} }
/* /*

View File

@@ -113,10 +113,7 @@
/* Variables */ /* Variables */
extern int hnsw_ef_search; extern int hnsw_ef_search;
extern int hnsw_entry_lock_tranche_id; extern int hnsw_lock_tranche_id;
extern int hnsw_allocator_lock_tranche_id;
extern int hnsw_flush_lock_tranche_id;
extern int hnsw_element_lock_tranche_id;
typedef struct HnswElementData HnswElementData; typedef struct HnswElementData HnswElementData;
typedef struct HnswNeighborArray HnswNeighborArray; typedef struct HnswNeighborArray HnswNeighborArray;

View File

@@ -400,7 +400,7 @@ UpdateNeighborsInMemory(char *base, FmgrInfo *procinfo, Oid collation, HnswEleme
* Update graph in memory * Update graph in memory
*/ */
static void static void
UpdateGraphInMemory(FmgrInfo *procinfo, Oid collation, HnswElement element, int m, int efConstruction, HnswElement entryPoint, HnswBuildState * buildstate) UpdateGraphInMemory(FmgrInfo *procinfo, Oid collation, HnswElement element, int m, int efConstruction, bool updateEntryPoint, HnswBuildState * buildstate)
{ {
HnswGraph *graph = buildstate->graph; HnswGraph *graph = buildstate->graph;
char *base = buildstate->hnswarea; char *base = buildstate->hnswarea;
@@ -416,7 +416,7 @@ UpdateGraphInMemory(FmgrInfo *procinfo, Oid collation, HnswElement element, int
UpdateNeighborsInMemory(base, procinfo, collation, element, m); UpdateNeighborsInMemory(base, procinfo, collation, element, m);
/* Update entry point if needed (already have lock) */ /* Update entry point if needed (already have lock) */
if (entryPoint == NULL || element->level > entryPoint->level) if (updateEntryPoint)
HnswPtrStore(base, graph->entryPoint, element); HnswPtrStore(base, graph->entryPoint, element);
} }
@@ -434,32 +434,29 @@ InsertTupleInMemory(HnswBuildState * buildstate, HnswElement element)
int efConstruction = buildstate->efConstruction; int efConstruction = buildstate->efConstruction;
int m = buildstate->m; int m = buildstate->m;
char *base = buildstate->hnswarea; char *base = buildstate->hnswarea;
bool updateEntryPoint;
/* Get entry point */ /* Get entry point */
LWLockAcquire(entryLock, LW_SHARED); LWLockAcquire(entryLock, LW_EXCLUSIVE);
entryPoint = HnswPtrAccess(base, graph->entryPoint); entryPoint = HnswPtrAccess(base, graph->entryPoint);
/* Prevent concurrent inserts when likely updating entry point */ /* Pause new inserts when updating entry point */
if (entryPoint == NULL || element->level > entryPoint->level) /* May still be in-flight inserts */
{ updateEntryPoint = entryPoint == NULL || element->level > entryPoint->level;
/* Release shared lock */
/* Release entry lock */
if (!updateEntryPoint)
LWLockRelease(entryLock); LWLockRelease(entryLock);
/* Get exclusive lock */
LWLockAcquire(entryLock, LW_EXCLUSIVE);
/* Get latest entry point after lock is acquired */
entryPoint = HnswPtrAccess(base, graph->entryPoint);
}
/* Find neighbors for element */ /* Find neighbors for element */
HnswFindElementNeighbors(base, element, entryPoint, NULL, procinfo, collation, m, efConstruction, false); HnswFindElementNeighbors(base, element, entryPoint, NULL, procinfo, collation, m, efConstruction, false);
/* Update graph in memory */ /* Update graph in memory */
UpdateGraphInMemory(procinfo, collation, element, m, efConstruction, entryPoint, buildstate); UpdateGraphInMemory(procinfo, collation, element, m, efConstruction, updateEntryPoint, buildstate);
/* Release entry lock */ /* Release entry lock */
LWLockRelease(entryLock); if (updateEntryPoint)
LWLockRelease(entryLock);
} }
/* /*
@@ -548,7 +545,7 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heaptid, Hn
HnswPtrStore(base, element->value, valuePtr); HnswPtrStore(base, element->value, valuePtr);
/* Create a lock for the element */ /* Create a lock for the element */
LWLockInitialize(&element->lock, hnsw_element_lock_tranche_id); LWLockInitialize(&element->lock, hnsw_lock_tranche_id);
/* Insert tuple */ /* Insert tuple */
InsertTupleInMemory(buildstate, element); InsertTupleInMemory(buildstate, element);
@@ -611,9 +608,9 @@ InitGraph(HnswGraph * graph, char *base, long memoryTotal)
graph->flushed = false; graph->flushed = false;
graph->indtuples = 0; graph->indtuples = 0;
SpinLockInit(&graph->lock); SpinLockInit(&graph->lock);
LWLockInitialize(&graph->entryLock, hnsw_entry_lock_tranche_id); LWLockInitialize(&graph->entryLock, hnsw_lock_tranche_id);
LWLockInitialize(&graph->allocatorLock, hnsw_allocator_lock_tranche_id); LWLockInitialize(&graph->allocatorLock, hnsw_lock_tranche_id);
LWLockInitialize(&graph->flushLock, hnsw_flush_lock_tranche_id); LWLockInitialize(&graph->flushLock, hnsw_lock_tranche_id);
} }
/* /*