Skip to content

Commit

Permalink
release 1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Hussama Ismail committed Sep 10, 2020
2 parents a11efa2 + 6620edf commit ffb0bfb
Show file tree
Hide file tree
Showing 20 changed files with 426 additions and 124 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This project contains a [JNA](https://github.com/java-native-access/jna) (Java N

### __Pre-Generated Shared Library__

The jar file includes some pre-generated libraries for _Windows_, _Debian Linux_ and _MacOS_ (x86-64) which should allow an easy integration and abstract all complexity related to compilation. In the case of operating system issues, a runtime exception will be thrown and the manual compilation will be advised.
The jar file includes some pre-generated libraries for _Windows_, _Debian Linux_ and _MacOS_ (x86-64) which should allow an easy integration and abstract all complexity related to compilation. An extra library for Debian Linux (aarch64) is also available for tests with AWS Graviton 2. In the case of operating system issues, a runtime exception will be thrown and the manual compilation will be advised.

__On Windows, the [Build Tools for Visual Studio 2019 (C++ build tools)](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) is required__.

Expand All @@ -20,7 +20,7 @@ Add the following dependency in your `pom.xml`:
<dependency>
<groupId>com.stepstone.search.hnswlib.jna</groupId>
<artifactId>hnswlib-jna</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
</dependency>
```

Expand All @@ -36,7 +36,7 @@ To generate the shared library required by this project, `binding.cpp` needs to
```
clang++ -O3 -shared bindings.cpp -I hnswlib -o <project_folder>/lib/libhnswlib-jna-x86-64.dylib
```
__Note:__ The shared library's name must be: __libhnswlib-jna-ARCH.EXT__ where `ARCH` is the canonical architecture name (e.g., `x86-64` for `amd64`, or `aarch64` for ARM64) and `EXT` is `dylib` for MacOS, for windows use `dll`, and linux `so`.
__Note:__ The shared library's name must be: __libhnswlib-jna-ARCH.EXT__ where `ARCH` is the canonical architecture name (e.g., `x86-64` for AMD64, or `aarch64` for ARM64) and `EXT` is `dylib` for MacOS, for windows use `dll`, and linux `so`.

#### Instructions for Windows

Expand Down
105 changes: 68 additions & 37 deletions bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <iostream>
#include <atomic>
#include <cmath>
#include "hnswlib/hnswlib.h"

#if _WIN32
Expand All @@ -28,8 +29,11 @@
#define RESULT_ITEM_CANNOT_BE_INSERTED_INTO_THE_VECTOR_SPACE 4
#define RESULT_ONCE_INDEX_IS_CLEARED_IT_CANNOT_BE_REUSED 5
#define RESULT_GET_DATA_FAILED 6
#define RESULT_ID_NOT_IN_INDEX 7
#define RESULT_INDEX_NOT_INITIALIZED 8

#define TRY_CATCH_RETURN_INT_BLOCK(block) if (index_cleared) return RESULT_ONCE_INDEX_IS_CLEARED_IT_CANNOT_BE_REUSED; int result_code = RESULT_SUCCESSFUL; try { block } catch (...) { result_code = RESULT_EXCEPTION_THROWN; }; return result_code;
#define TRY_CATCH_NO_INITIALIZE_CHECK_AND_RETURN_INT_BLOCK(block) if (index_cleared) return RESULT_ONCE_INDEX_IS_CLEARED_IT_CANNOT_BE_REUSED; int result_code = RESULT_SUCCESSFUL; try { block } catch (...) { result_code = RESULT_EXCEPTION_THROWN; }; return result_code;
#define TRY_CATCH_RETURN_INT_BLOCK(block) if (!index_initialized) return RESULT_INDEX_NOT_INITIALIZED; TRY_CATCH_NO_INITIALIZE_CHECK_AND_RETURN_INT_BLOCK(block)

template<typename dist_t, typename data_t=float>
class Index {
Expand All @@ -46,19 +50,17 @@ class Index {
data_must_be_normalized = true;
}
appr_alg = NULL;
ep_added = true;
index_initialized = false;
index_cleared = false;
}

int init_new_index(const size_t maxElements, const size_t M, const size_t efConstruction, const size_t random_seed) {
TRY_CATCH_RETURN_INT_BLOCK({
TRY_CATCH_NO_INITIALIZE_CHECK_AND_RETURN_INT_BLOCK({
if (appr_alg) {
return RESULT_INDEX_ALREADY_INITIALIZED;
}
appr_alg = new hnswlib::HierarchicalNSW<dist_t>(l2space, maxElements, M, efConstruction, random_seed);
index_initialized = true;
ep_added = false;
});
}

Expand All @@ -68,11 +70,15 @@ class Index {
});
}

size_t get_ef_construction() {
int get_ef() {
return appr_alg->ef_;
}

int get_ef_construction() {
return appr_alg->ef_construction_;
}

size_t get_M() {
int get_M() {
return appr_alg->M_;
}

Expand All @@ -83,7 +89,7 @@ class Index {
}

int load_index(const std::string &path_to_index, size_t max_elements) {
TRY_CATCH_RETURN_INT_BLOCK({
TRY_CATCH_NO_INITIALIZE_CHECK_AND_RETURN_INT_BLOCK({
if (appr_alg) {
std::cerr << "Warning: Calling load_index for an already initialized index. Old index is being deallocated.";
delete appr_alg;
Expand Down Expand Up @@ -116,33 +122,41 @@ class Index {
});
}

bool hasId(int id) {
int label_c;
auto search = (appr_alg->label_lookup_.find(id));
if (search == (appr_alg->label_lookup_.end()) || (appr_alg->isMarkedDeleted(search->second))) {
return false;
}
return true;
int hasId(int id) {
TRY_CATCH_RETURN_INT_BLOCK({
int label_c;
auto search = (appr_alg->label_lookup_.find(id));
if (search == (appr_alg->label_lookup_.end()) || (appr_alg->isMarkedDeleted(search->second))) {
return RESULT_ID_NOT_IN_INDEX;
}
});
}

int getDataById(int id, float* data, int dim) {
int label_c;
auto search = (appr_alg->label_lookup_.find(id));
if (search == (appr_alg->label_lookup_.end()) || (appr_alg->isMarkedDeleted(search->second))) {
return RESULT_GET_DATA_FAILED;
}
label_c = search->second;
char* data_ptrv = (appr_alg->getDataByInternalId(label_c));
float* data_ptr = (float*) data_ptrv;
for (int i = 0; i < dim; i++) {
data[i] = *data_ptr;
data_ptr += 1;
}
return RESULT_SUCCESSFUL;
TRY_CATCH_RETURN_INT_BLOCK({
int label_c;
auto search = (appr_alg->label_lookup_.find(id));
if (search == (appr_alg->label_lookup_.end()) || (appr_alg->isMarkedDeleted(search->second))) {
return RESULT_ID_NOT_IN_INDEX;
}
label_c = search->second;
char* data_ptrv = (appr_alg->getDataByInternalId(label_c));
float* data_ptr = (float*) data_ptrv;
for (int i = 0; i < dim; i++) {
data[i] = *data_ptr;
data_ptr += 1;
}
});
}

float compute_similarity(float* vector1, float* vector2) {
return (appr_alg -> fstdistfunc_(vector1, vector2, (appr_alg -> dist_func_param_)));
float similarity;
try {
similarity = (appr_alg->fstdistfunc_(vector1, vector2, (appr_alg -> dist_func_param_)));
} catch (...) {
similarity = NAN;
}
return similarity;
}

int knn_query(float* input, bool input_normalized, int k, int* indices /* output */, float* coefficients /* output */) {
Expand All @@ -163,8 +177,10 @@ class Index {
});
}

void mark_deleted(size_t label) {
appr_alg->markDelete(label);
int mark_deleted(int label) {
TRY_CATCH_RETURN_INT_BLOCK({
appr_alg->markDelete(label);
});
}

void resize_index(size_t new_size) {
Expand All @@ -180,7 +196,7 @@ class Index {
}

int clear_index() {
TRY_CATCH_RETURN_INT_BLOCK({
TRY_CATCH_NO_INITIALIZE_CHECK_AND_RETURN_INT_BLOCK({
delete l2space;
if (appr_alg)
delete appr_alg;
Expand All @@ -190,7 +206,6 @@ class Index {

std::string space_name;
int dim;
bool ep_added;
bool index_cleared;
bool index_initialized;
bool data_must_be_normalized;
Expand All @@ -214,7 +229,7 @@ EXTERN_C DLLEXPORT Index<float>* createNewIndex(char* spaceName, int dimension){
}

EXTERN_C DLLEXPORT int initNewIndex(Index<float>* index, int maxNumberOfElements, int M = 16, int efConstruction = 200, int randomSeed = 100) {
return index->init_new_index(maxNumberOfElements, M, efConstruction, randomSeed);
return index->init_new_index(maxNumberOfElements, M, efConstruction, randomSeed);
}

EXTERN_C DLLEXPORT int addItemToIndex(float* item, int normalized, int label, Index<float>* index) {
Expand Down Expand Up @@ -252,15 +267,31 @@ EXTERN_C DLLEXPORT int setEf(Index<float>* index, int ef) {
}

EXTERN_C DLLEXPORT int getData(Index<float>* index, int id, float* vector, int dim) {
return index-> getDataById(id, vector, dim);
return index->getDataById(id, vector, dim);
}

EXTERN_C DLLEXPORT bool hasId(Index<float>* index, int id) {
return index-> hasId(id);
EXTERN_C DLLEXPORT int hasId(Index<float>* index, int id) {
return index->hasId(id);
}

EXTERN_C DLLEXPORT float computeSimilarity(Index<float>* index, float* vector1, float* vector2) {
return index -> compute_similarity(vector1, vector2);
return index->compute_similarity(vector1, vector2);
}

EXTERN_C DLLEXPORT int getM(Index<float>* index) {
return index->get_M();
}

EXTERN_C DLLEXPORT int getEfConstruction(Index<float>* index) {
return index->get_ef_construction();
}

EXTERN_C DLLEXPORT int getEf(Index<float>* index) {
return index->get_ef();
}

EXTERN_C DLLEXPORT int markDeleted(Index<float>* index, int id) {
return index->mark_deleted(id);
}

int main(){
Expand Down
4 changes: 2 additions & 2 deletions hnswlib-jna-example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<parent>
<groupId>com.stepstone.search.hnswlib.jna</groupId>
<artifactId>hnswlib-jna-parent</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
<relativePath>..</relativePath>
</parent>

Expand All @@ -32,7 +32,7 @@
<dependency>
<groupId>com.stepstone.search.hnswlib.jna</groupId>
<artifactId>hnswlib-jna</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ private static void exampleOfACosineIndex() {

Index indexCosine = new Index(SpaceName.COSINE, 7);
indexCosine.initialize(3);
indexCosine.addNormalizedItem(i1, 1_111_111); /* 1_111_111 is a label */
indexCosine.addNormalizedItem(i1, 1_111_111); /* 1_111_111 is an ID */
indexCosine.addNormalizedItem(i2, 2_222_222);
indexCosine.addNormalizedItem(i3); /* if not defined, an incremental label will be automatically assigned */
indexCosine.addNormalizedItem(i3); /* if not defined, an incremental ID will be automatically assigned */

float[] input = new float[] {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
Index.normalize(input);
Expand All @@ -39,7 +39,7 @@ private static void exampleOfACosineIndex() {

System.out.println("Cosine Index - Query Results: ");
System.out.println(Arrays.toString(cosineQT.getCoefficients()));
System.out.println(Arrays.toString(cosineQT.getLabels()));
System.out.println(Arrays.toString(cosineQT.getIds()));
indexCosine.clear();
}

Expand All @@ -51,17 +51,17 @@ private static void exampleOfAInnerProductIndex() {
Index indexIP = new Index(SpaceName.IP, 7);
indexIP.initialize(3, 16, 100, 200); /* set maxNumberOfElements, m, efConstruction and randomSeed */
indexIP.setEf(10);
indexIP.addItem(i1, 1_111_111); /* 1_111_111 is a label */
indexIP.addItem(i1, 1_111_111); /* 1_111_111 is an ID */
indexIP.addItem(i2, 0xCAFECAFE);
indexIP.addItem(i3); /* if not defined, an incremental label will be automatically assigned */
indexIP.addItem(i3); /* if not defined, an incremental ID will be automatically assigned */

float[] input = new float[] {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};

QueryTuple ipQT = indexIP.knnQuery(input, 3);

System.out.println("Inner Product Index - Query Results: ");
System.out.println(Arrays.toString(ipQT.getCoefficients()));
System.out.println(Arrays.toString(ipQT.getLabels()));
System.out.println(Arrays.toString(ipQT.getIds()));
indexIP.clear();
}

Expand Down
6 changes: 3 additions & 3 deletions hnswlib-jna-legacy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<name>hnswlib-jna-legacy</name>
<artifactId>hnswlib-jna-legacy</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>

<licenses>
<license>
Expand All @@ -18,12 +18,12 @@
<parent>
<groupId>com.stepstone.search.hnswlib.jna</groupId>
<artifactId>hnswlib-jna-parent</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
<relativePath>..</relativePath>
</parent>

<properties>
<hnswlib.jna.version>1.3.1</hnswlib.jna.version>
<hnswlib.jna.version>1.4.0</hnswlib.jna.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
Expand Down
4 changes: 2 additions & 2 deletions hnswlib-jna/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<name>hnswlib-jna</name>
<artifactId>hnswlib-jna</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>

<licenses>
<license>
Expand All @@ -18,7 +18,7 @@
<parent>
<groupId>com.stepstone.search.hnswlib.jna</groupId>
<artifactId>hnswlib-jna-parent</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
<relativePath>..</relativePath>
</parent>

Expand Down
Loading

0 comments on commit ffb0bfb

Please sign in to comment.