-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sq for hnsw #311
Add sq for hnsw #311
Conversation
@hhy3 🔍 Important: PR Classification Needed! For efficient project management and a seamless review process, it's essential to classify your PR correctly. Here's how:
For any PR outside the kind/improvement category, ensure you link to the associated issue using the format: “issue: #”. Thanks for your efforts and contribution to the community!. |
/kind feature |
15978fe
to
8740a81
Compare
include/knowhere/comp/index_param.h
Outdated
@@ -43,6 +43,7 @@ constexpr const char* INDEX_RAFT_IVFPQ = "GPU_RAFT_IVF_PQ"; | |||
constexpr const char* INDEX_RAFT_CAGRA = "GPU_RAFT_CAGRA"; | |||
|
|||
constexpr const char* INDEX_HNSW = "HNSW"; | |||
constexpr const char* INDEX_HNSW_SQ = "HNSW_SQ"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not HNSW_SQ8
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be HNSW_SQ8
include/knowhere/utils.h
Outdated
hash_u8_vec(const uint8_t* x, size_t d) { | ||
uint64_t h = seed; | ||
for (size_t i = 0; i < d; ++i) { | ||
h = h * 13331 + *(uint8_t*)(x + i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h = h * 13331 + x[i];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
@@ -215,5 +215,28 @@ fvec_L2sqr_batch_4_avx(const float* x, const float* y0, const float* y1, const f | |||
} | |||
FAISS_PRAGMA_IMPRECISE_FUNCTION_END | |||
|
|||
// trust the compiler to unroll this properly | |||
int32_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please confirm that it is int32_t
, not uint32_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems no big difference between int32_t and uint32_t
data_norm = knowhere::CopyAndNormalizeVecs(from, 1, dim); | ||
from = data_norm.get(); | ||
} | ||
for (size_t i = 0; i < dim; ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please confirm that is it really int8_t
, not uint8_t
.
Classical SQ implementation uses uint8_t and maps into [0, 255] range, not [-128, 127].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SQ used there is symmetric version which maps to [-127, 127], which unify ip and l2 metric and simplify implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be good to add some rough comments about SQ types here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
src/index/hnsw/hnsw_config.h
Outdated
@@ -85,6 +85,14 @@ class HnswConfig : public BaseConfig { | |||
} | |||
}; | |||
|
|||
class HnswSQConfig : public HnswConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use the same user api with scann, by using "with_raw_data" option? Also, do we need another refine param like "reorder_k" used in scann
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
9340554
to
fd8a399
Compare
mutable knowhere::lru_cache<uint64_t, tableint> lru_cache; | ||
|
||
void | ||
trainSQuant(const float* train_data, size_t ntrain) { | ||
size_t dim = *(size_t*)dist_func_param_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add alpha_ = 0;
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
} | ||
for (size_t i = 0; i < dim; ++i) { | ||
float x = from[i] / alpha_; | ||
if (x > 1.0f) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this implementation assumes that the data distribution is symmetric around 0, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It's the most common scenario
_mm_prefetch(getSQDataByInternalId(id), _MM_HINT_T0); | ||
} else { | ||
_mm_prefetch(getDataByInternalId(id), _MM_HINT_T0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just mentioning that this is x86-only code, unless USE_PREFETCH
is enabled for x86 only as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to centralized these platform related code just like what we do for distance hook. Created an issue to track #416.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using the hook mechanism for prefetching is a horrible idea
class CosineSpace : public SpaceInterface<float> { | ||
DISTFUNC<float> fstdistfunc_; | ||
DISTFUNC<float> fstdistfunc_sq_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The introduction of an additional entity fstdistfunc_sq_
is needed, because SpaceInterface<>
struct does not distinguish between underlying datatypes, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
src/index/hnsw/hnsw.cc
Outdated
@@ -27,6 +27,7 @@ | |||
#include "knowhere/utils.h" | |||
|
|||
namespace knowhere { | |||
template <bool USE_SQ> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specify SQ8 here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
src/index/hnsw/hnsw.cc
Outdated
@@ -477,7 +489,7 @@ class HnswIndexNode : public IndexNode { | |||
|
|||
std::string | |||
Type() const override { | |||
return knowhere::IndexEnum::INDEX_HNSW; | |||
return USE_SQ ? knowhere::IndexEnum::INDEX_HNSW_SQ8 : knowhere::IndexEnum::INDEX_HNSW; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use constexpr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
src/index/hnsw/hnsw.cc
Outdated
@@ -27,6 +27,7 @@ | |||
#include "knowhere/utils.h" | |||
|
|||
namespace knowhere { | |||
template <bool USE_SQ> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's create a enum class type for this, in case we have SQ8, SQ4, PQ in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
thirdparty/hnswlib/hnswlib/hnswalg.h
Outdated
@@ -67,11 +67,13 @@ class HierarchicalNSW : public AlgorithmInterface<dist_t> { | |||
} | |||
|
|||
HierarchicalNSW(SpaceInterface<dist_t>* s, size_t max_elements, size_t M = 16, size_t ef_construction = 200, | |||
size_t random_seed = 100) | |||
bool use_sq = false, bool use_sq_refine = false, size_t random_seed = 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these two new params are coupled. Let's make a new constructor for SQ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or why not make SQ a template the same as HNSWIndexNode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea
thirdparty/hnswlib/hnswlib/hnswalg.h
Outdated
offsetData_ = size_links_level0_; | ||
if (use_sq) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mixed usage of use_sq
and sq_enabled_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'll fix it
mutable knowhere::lru_cache<uint64_t, tableint> lru_cache; | ||
|
||
void | ||
trainSQuant(const float* train_data, size_t ntrain) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are adopting symmetrical global SQ. Plz make a note here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
data_norm = knowhere::CopyAndNormalizeVecs(from, 1, dim); | ||
from = data_norm.get(); | ||
} | ||
for (size_t i = 0; i < dim; ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be good to add some rough comments about SQ types here.
_mm_prefetch(getSQDataByInternalId(id), _MM_HINT_T0); | ||
} else { | ||
_mm_prefetch(getDataByInternalId(id), _MM_HINT_T0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to centralized these platform related code just like what we do for distance hook. Created an issue to track #416.
Signed-off-by: zh Wang <[email protected]>
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: hhy3, liliu-z The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
issue: #312