Skip to content
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

Fix 456 (unaligned memory for Hamming) #457

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
21 changes: 15 additions & 6 deletions src/annoylib.h
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ struct Hamming : Base {
};

static const size_t max_iterations = 20;

template<typename T>
static inline T pq_distance(T distance, T margin, int child_nr) {
return distance - (margin != (unsigned int) child_nr);
Expand All @@ -650,16 +649,25 @@ struct Hamming : Base {
template<typename S, typename T>
static inline T distance(const Node<S, T>* x, const Node<S, T>* y, int f) {
size_t dist = 0;
// As a dumb workaround to #456 we copy it to an address that's guaranteed to be aligned
T* x_v = (T*)alloca(sizeof(T)*f);
T* y_v = (T*)alloca(sizeof(T)*f);
memcpy(x_v, x->v, sizeof(T)*f);
memcpy(y_v, y->v, sizeof(T)*f);
for (int i = 0; i < f; i++) {
dist += popcount(x->v[i] ^ y->v[i]);
dist += popcount(x_v[i] ^ y_v[i]);
}
return dist;
}
template<typename S, typename T>
static inline bool margin(const Node<S, T>* n, const T* y, int f) {
static const size_t n_bits = sizeof(T) * 8;
T chunk = n->v[0] / n_bits;
return (y[chunk] & (static_cast<T>(1) << (n_bits - 1 - (n->v[0] % n_bits)))) != 0;
T index;
memcpy(&index, &n->v[0], sizeof(T)); // # 456, equivalent to index = n->v[0]
T chunk = index / n_bits, offset = index % n_bits;
T y_chunk;
memcpy(&y_chunk, &y[chunk], sizeof(T)); // #456
return (y_chunk & (static_cast<T>(1) << (n_bits - 1 - offset))) != 0;
}
template<typename S, typename T, typename Random>
static inline bool side(const Node<S, T>* n, const T* y, int f, Random& random) {
Expand All @@ -672,7 +680,8 @@ struct Hamming : Base {
int dim = f * 8 * sizeof(T);
for (; i < max_iterations; i++) {
// choose random position to split at
n->v[0] = random.index(dim);
T index = random.index(dim);
memcpy(&n->v[0], &index, sizeof(T)); // #456, equivalent to n->v[0] = index
cur_size = 0;
for (typename vector<Node<S, T>*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
if (margin(n, (*it)->v, f)) {
Expand All @@ -687,7 +696,7 @@ struct Hamming : Base {
if (i == max_iterations) {
int j = 0;
for (; j < dim; j++) {
n->v[0] = j;
memcpy(&n->v[0], &j, sizeof(T)); // #456, equivalent to n->v[0] = j;
cur_size = 0;
for (typename vector<Node<S, T>*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
if (margin(n, (*it)->v, f)) {
Expand Down