Krotos Modules 3
Loading...
Searching...
No Matches
hnswlib.h
Go to the documentation of this file.
1#pragma once
2#ifndef NO_MANUAL_VECTORIZATION
3//#ifdef __SSE__
4//#define USE_SSE
5#ifdef __AVX__
6#define USE_AVX
7#ifdef __AVX512F__
8#define USE_AVX512
9#endif
10#endif
11#endif
12//#endif
13
14#if defined(USE_AVX) || defined(USE_SSE)
15#ifdef _MSC_VER
16#include <intrin.h>
17#include <stdexcept>
18#include "cpu_x86.h"
19void cpu_x86::cpuid(int32_t out[4], int32_t eax, int32_t ecx) {
20 __cpuidex(out, eax, ecx);
21}
22__int64 xgetbv(unsigned int x) {
23 return _xgetbv(x);
24}
25#else
26#include <x86intrin.h>
27#include <cpuid.h>
28#include <stdint.h>
29void cpuid(int32_t cpuInfo[4], int32_t eax, int32_t ecx) {
30 __cpuid_count(eax, ecx, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
31}
32uint64_t xgetbv(unsigned int index) {
33 uint32_t eax, edx;
34 __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
35 return ((uint64_t)edx << 32) | eax;
36}
37#endif
38
39#if defined(USE_AVX512)
40#include <immintrin.h>
41#endif
42
43#if defined(__GNUC__)
44#define PORTABLE_ALIGN32 __attribute__((aligned(32)))
45#define PORTABLE_ALIGN64 __attribute__((aligned(64)))
46#else
47#define PORTABLE_ALIGN32 __declspec(align(32))
48#define PORTABLE_ALIGN64 __declspec(align(64))
49#endif
50
51// Adapted from https://github.com/Mysticial/FeatureDetector
52#define _XCR_XFEATURE_ENABLED_MASK 0
53
54bool AVXCapable() {
55 int cpuInfo[4];
56
57 // CPU support
58 cpuid(cpuInfo, 0, 0);
59 int nIds = cpuInfo[0];
60
61 bool HW_AVX = false;
62 if (nIds >= 0x00000001) {
63 cpuid(cpuInfo, 0x00000001, 0);
64 HW_AVX = (cpuInfo[2] & ((int)1 << 28)) != 0;
65 }
66
67 // OS support
68 cpuid(cpuInfo, 1, 0);
69
70 bool osUsesXSAVE_XRSTORE = (cpuInfo[2] & (1 << 27)) != 0;
71 bool cpuAVXSuport = (cpuInfo[2] & (1 << 28)) != 0;
72
73 bool avxSupported = false;
74 if (osUsesXSAVE_XRSTORE && cpuAVXSuport) {
75 uint64_t xcrFeatureMask = xgetbv(_XCR_XFEATURE_ENABLED_MASK);
76 avxSupported = (xcrFeatureMask & 0x6) == 0x6;
77 }
78 return HW_AVX && avxSupported;
79}
80
81bool AVX512Capable() {
82 if (!AVXCapable()) return false;
83
84 int cpuInfo[4];
85
86 // CPU support
87 cpuid(cpuInfo, 0, 0);
88 int nIds = cpuInfo[0];
89
90 bool HW_AVX512F = false;
91 if (nIds >= 0x00000007) { // AVX512 Foundation
92 cpuid(cpuInfo, 0x00000007, 0);
93 HW_AVX512F = (cpuInfo[1] & ((int)1 << 16)) != 0;
94 }
95
96 // OS support
97 cpuid(cpuInfo, 1, 0);
98
99 bool osUsesXSAVE_XRSTORE = (cpuInfo[2] & (1 << 27)) != 0;
100 bool cpuAVXSuport = (cpuInfo[2] & (1 << 28)) != 0;
101
102 bool avx512Supported = false;
103 if (osUsesXSAVE_XRSTORE && cpuAVXSuport) {
104 uint64_t xcrFeatureMask = xgetbv(_XCR_XFEATURE_ENABLED_MASK);
105 avx512Supported = (xcrFeatureMask & 0xe6) == 0xe6;
106 }
107 return HW_AVX512F && avx512Supported;
108}
109#endif
110
111#include <queue>
112#include <vector>
113#include <iostream>
114#include <string.h>
115
116namespace hnswlib {
117 typedef size_t labeltype;
118
119 template <typename T>
121 public:
122 bool operator()(const T& p1, const T& p2) {
123 return p1.first > p2.first;
124 }
125 };
126
127 template<typename T>
128 static void writeBinaryPOD(std::ostream &out, const T &podRef) {
129 out.write((char *) &podRef, sizeof(T));
130 }
131
132 template<typename T>
133 static void readBinaryPOD(std::istream &in, T &podRef) {
134 in.read((char *) &podRef, sizeof(T));
135 }
136
137 template<typename MTYPE>
138 using DISTFUNC = MTYPE(*)(const void *, const void *, const void *);
139
140
141 template<typename MTYPE>
143 public:
144 //virtual void search(void *);
145 virtual size_t get_data_size() = 0;
146
148
149 virtual void *get_dist_func_param() = 0;
150
151 virtual ~SpaceInterface() {}
152 };
153
154 template<typename dist_t>
156 public:
157 virtual void addPoint(const void *datapoint, labeltype label)=0;
158 virtual std::priority_queue<std::pair<dist_t, labeltype >> searchKnn(const void *, size_t) const = 0;
159
160 // Return k nearest neighbor in the order of closer fist
161 virtual std::vector<std::pair<dist_t, labeltype>>
162 searchKnnCloserFirst(const void* query_data, size_t k) const;
163
164 virtual void saveIndex(const std::string &location)=0;
166 }
167 };
168
169 template<typename dist_t>
170 std::vector<std::pair<dist_t, labeltype>>
171 AlgorithmInterface<dist_t>::searchKnnCloserFirst(const void* query_data, size_t k) const {
172 std::vector<std::pair<dist_t, labeltype>> result;
173
174 // here searchKnn returns the result in the order of further first
175 auto ret = searchKnn(query_data, k);
176 {
177 size_t sz = ret.size();
178 result.resize(sz);
179 while (!ret.empty()) {
180 result[--sz] = ret.top();
181 ret.pop();
182 }
183 }
184
185 return result;
186 }
187}
188
189#include "space_l2.h"
190#include "space_ip.h"
191#include "bruteforce.h"
192#include "hnswalg.h"
Definition hnswlib.h:155
virtual ~AlgorithmInterface()
Definition hnswlib.h:165
virtual void saveIndex(const std::string &location)=0
virtual std::vector< std::pair< dist_t, labeltype > > searchKnnCloserFirst(const void *query_data, size_t k) const
Definition hnswlib.h:171
virtual void addPoint(const void *datapoint, labeltype label)=0
virtual std::priority_queue< std::pair< dist_t, labeltype > > searchKnn(const void *, size_t) const =0
Definition hnswlib.h:142
virtual size_t get_data_size()=0
virtual ~SpaceInterface()
Definition hnswlib.h:151
virtual void * get_dist_func_param()=0
virtual DISTFUNC< MTYPE > get_dist_func()=0
Definition hnswlib.h:120
bool operator()(const T &p1, const T &p2)
Definition hnswlib.h:122
Definition bruteforce.h:7
size_t labeltype
Definition hnswlib.h:117
static void writeBinaryPOD(std::ostream &out, const T &podRef)
Definition hnswlib.h:128
static void readBinaryPOD(std::istream &in, T &podRef)
Definition hnswlib.h:133
MTYPE(*)(const void *, const void *, const void *) DISTFUNC
Definition hnswlib.h:138