Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/my_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,25 @@ static inline void MY_RELAX_CPU(void)
}


/*
Hint the CPU to start loading a cache line for reading.

Like YieldProcessor() above, PreFetchCacheLine() is architecture-independent:
winnt.h picks the instruction per target, unlike _mm_prefetch().
clang-cl defines __clang__ but not __GNUC__, so it must take the first branch.
*/
static inline void my_prefetch(const void *addr)
{
#if defined(__GNUC__) || defined(__clang__)
__builtin_prefetch(addr, 0, 3);
#elif defined(_WIN32)
PreFetchCacheLine(PF_TEMPORAL_LEVEL_1, addr);
#else
(void) addr;
#endif
}


#ifdef HAVE_PAUSE_INSTRUCTION
# ifdef __cplusplus
extern "C" {
Expand Down
14 changes: 14 additions & 0 deletions sql/vector_mhnsw.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "vector_mhnsw.h"
#include <scope.h>
#include <my_atomic_wrapper.h>
#include <my_cpu.h> // my_prefetch()
#include "bloom_filters.h"

// distance can be a little bit < 0 because of fast math
Expand Down Expand Up @@ -1347,6 +1348,19 @@ static int search_layer(MHNSW_param *p, const FVector *target, float threshold,
if (res == 0xff)
continue;

// A node and its vector share one allocation. Prefetch unseen nodes before
// computing distances so later loads can overlap with work on earlier ones.
for (size_t i= 0; i < 8; i++)
{
FVectorNode *link= links[i];
if (!(res & (1 << i)) && link)
{
my_prefetch(link);
my_prefetch(reinterpret_cast<const char*>(link)
+ CPU_LEVEL1_DCACHE_LINESIZE);
}
}

for (size_t i= 0; i < 8; i++)
{
if (res & (1 << i))
Expand Down