Skip to content
This repository was archived by the owner on Nov 21, 2024. It is now read-only.

Product Quantizer implementation #37

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bbd4fff
Implement product quantizer
Aug 10, 2023
91726b3
Update pq test to show index size
Aug 10, 2023
560a60b
Fix GCC build
Aug 11, 2023
5672b36
Fix GCC build
Aug 11, 2023
78a4267
Fix GCC build
Aug 11, 2023
d152c55
Merge with main
Aug 11, 2023
b9da52f
Use simple hash
Aug 11, 2023
efc6897
Update expected file
Aug 12, 2023
d2bb2da
Use OpenMP
Aug 12, 2023
af5eac7
Use OpenMP
Aug 12, 2023
3dbb157
Add alternative version of expected output of pq test for PG14
Aug 12, 2023
f7eba62
Support OpenMP at OS/X
Aug 12, 2023
ac2c19e
Yet another version of pq.sql test output
Aug 12, 2023
4798183
:Do not output distance in pq.sql test because it is slightly differe…
Aug 13, 2023
5d6f06f
Do not build with OpenMp at OS/X
Aug 13, 2023
fcc3e6d
Early stop of training
Aug 16, 2023
8bff9c0
Fix problem with OpenMP in compute_centroids
Aug 17, 2023
3090e93
Fix bug in pq_create_centroids
Aug 17, 2023
3c90331
Fix bug in initialization of PQ pages
Aug 17, 2023
b1cd4f6
Stop PQ iterations if improvement is smaller than threshold
Aug 18, 2023
54ba50b
Restore redo loop for PQ tranining
Aug 19, 2023
4c81918
Minor refactoring
Aug 19, 2023
e11e2e3
Minor refactoring
Aug 19, 2023
27ba8bd
Increase max_points_per_centroid
Aug 19, 2023
2703a06
Simplify code
Aug 20, 2023
139c4fd
Use hypercube for centroids initialization
Aug 22, 2023
a4ecdcb
Implement principal component analysis for PQ training
Aug 22, 2023
cd38761
Remove occasinally added object file
Aug 22, 2023
e89ff87
Add missed assert.h include
Aug 22, 2023
a311aec
Fix GCC warnings
Aug 22, 2023
c0fdd3c
Fix GCC warnings
Aug 22, 2023
abcf100
Perform subsampling after hypercube initialization
Aug 22, 2023
f9539e2
Define bigidx_t as replacement of FAISS idx_t
Aug 23, 2023
1664ae8
Define bigidx_t as replacement of FAISS idx_t
Aug 23, 2023
13b67e9
Onemore refactoring of vector transform code
Aug 24, 2023
79f9090
Onemore refactoring of vector transform code
Aug 24, 2023
190adad
Add overflow checks
Aug 24, 2023
4a86c88
Use kmeans as default train algoeithm
Aug 25, 2023
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
Prev Previous commit
Next Next commit
Define bigidx_t as replacement of FAISS idx_t
  • Loading branch information
Konstantin Knizhnik committed Aug 23, 2023
commit f9539e2d81ccf01e192c9e084db4d603ad79b5f4
34 changes: 17 additions & 17 deletions transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ void matrix_qr(int m, int n, float* a) {
float work_size;

sgeqrf_(&mi, &ni, a, &mi, tau.data(), &work_size, &lwork, &info);
lwork = size_t(work_size);
lwork = (FINTEGER)work_size;
std::vector<float> work(lwork);

sgeqrf_(&mi, &ni, a, &mi, tau.data(), work.data(), &lwork, &info);
Expand All @@ -260,17 +260,17 @@ rand_perm(int* perm, size_t n, int64_t seed) {
* VectorTransform
*********************************************/

float* VectorTransform::apply(size_t n, const float* x) const {
float* VectorTransform::apply(bigidx_t n, const float* x) const {
float* xt = new float[n * d_out];
apply_noalloc(n, x, xt);
return xt;
}

void VectorTransform::train(size_t, const float*) {
void VectorTransform::train(bigidx_t, const float*) {
// does nothing by default
}

void VectorTransform::reverse_transform(size_t, const float*, float*) const {
void VectorTransform::reverse_transform(bigidx_t, const float*, float*) const {
assert(false);
}

Expand All @@ -291,14 +291,14 @@ LinearTransform::LinearTransform(int d_in, int d_out, bool have_bias)
is_trained = false; // will be trained when A and b are initialized
}

void LinearTransform::apply_noalloc(size_t n, const float* x, float* xt) const {
void LinearTransform::apply_noalloc(bigidx_t n, const float* x, float* xt) const {
assert(is_trained);

float c_factor;
if (have_bias) {
assert(b.size() == (size_t)d_out);
float* xi = xt;
for (size_t i = 0; i < n; i++)
for (bigidx_t i = 0; i < n; i++)
for (int j = 0; j < d_out; j++)
*xi++ = b[j];
c_factor = 1.0;
Expand All @@ -325,13 +325,13 @@ void LinearTransform::apply_noalloc(size_t n, const float* x, float* xt) const {
&nbiti);
}

void LinearTransform::transform_transpose(size_t n, const float* y, float* x)
void LinearTransform::transform_transpose(bigidx_t n, const float* y, float* x)
const {
if (have_bias) { // allocate buffer to store bias-corrected data
float* y_new = new float[n * d_out];
const float* yr = y;
float* yw = y_new;
for (size_t i = 0; i < n; i++) {
for (bigidx_t i = 0; i < n; i++) {
for (int j = 0; j < d_out; j++) {
*yw++ = *yr++ - b[j];
}
Expand Down Expand Up @@ -407,7 +407,7 @@ void LinearTransform::set_is_orthonormal() {
}
}

void LinearTransform::reverse_transform(size_t n, const float* xt, float* x)
void LinearTransform::reverse_transform(bigidx_t n, const float* xt, float* x)
const {
if (is_orthonormal) {
transform_transpose(n, xt, x);
Expand Down Expand Up @@ -470,7 +470,7 @@ void RandomRotationMatrix::init(int seed) {
is_trained = true;
}

void RandomRotationMatrix::train(size_t /*n*/, const float* /*x*/) {
void RandomRotationMatrix::train(bigidx_t /*n*/, const float* /*x*/) {
// initialize with some arbitrary seed
init(12345);
}
Expand Down Expand Up @@ -560,7 +560,7 @@ void eig(size_t d_in, double* cov, double* eigenvalues, int verbose) {
}
}

void PCAMatrix::train(size_t n, const float* x_in) {
void PCAMatrix::train(bigidx_t n, const float* x_in) {
const float* x = fvecs_maybe_subsample(
d_in, (size_t*)&n, max_points_per_d * d_in, x_in, verbose);
TransformedVectors tv(x_in, x);
Expand All @@ -570,7 +570,7 @@ void PCAMatrix::train(size_t n, const float* x_in) {
mean.resize(d_in, 0.0);
if (have_bias) { // we may want to skip the bias
const float* xi = x;
for (size_t i = 0; i < n; i++) {
for (bigidx_t i = 0; i < n; i++) {
for (int j = 0; j < d_in; j++)
mean[j] += *xi++;
}
Expand All @@ -584,7 +584,7 @@ void PCAMatrix::train(size_t n, const float* x_in) {
printf("]\n");
}

if (n >= (size_t)d_in) {
if (n >= d_in) {
// compute covariance matrix, store it in PCA matrix
PCAMat.resize(d_in * d_in);
float* cov = PCAMat.data();
Expand Down Expand Up @@ -637,7 +637,7 @@ void PCAMatrix::train(size_t n, const float* x_in) {
} else {
std::vector<float> xc(n * d_in);

for (size_t i = 0; i < n; i++)
for (int i = 0; i < n; i++)
for (int j = 0; j < d_in; j++)
xc[i * d_in + j] = x[i * d_in + j] - mean[j];

Expand All @@ -661,8 +661,8 @@ void PCAMatrix::train(size_t n, const float* x_in) {
if (verbose && d_in <= 10) {
float* ci = gram.data();
printf("gram=\n");
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++)
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%10g ", *ci++);
printf("\n");
}
Expand Down Expand Up @@ -710,7 +710,7 @@ void PCAMatrix::train(size_t n, const float* x_in) {
if (verbose && d_in <= 10) {
float* ci = PCAMat.data();
printf("PCAMat=\n");
for (size_t i = 0; i < n; i++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < d_in; j++)
printf("%10g ", *ci++);
printf("\n");
Expand Down
20 changes: 11 additions & 9 deletions transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct TransformedVectors {
}
};

typedef int64_t bigidx_t;

/** Any transformation applied on a set of vectors */
struct VectorTransform {
int d_in; ///! input dimension
Expand All @@ -64,25 +66,25 @@ struct VectorTransform {
* @param n nb of training vectors
* @param x training vecors, size n * d
*/
virtual void train(size_t n, const float* x);
virtual void train(bigidx_t n, const float* x);

/** apply the transformation and return the result in an allocated pointer
* @param n number of vectors to transform
* @param x input vectors, size n * d_in
* @return output vectors, size n * d_out
*/
float* apply(size_t n, const float* x) const;
float* apply(bigidx_t n, const float* x) const;

/** apply the transformation and return the result in a provided matrix
* @param n number of vectors to transform
* @param x input vectors, size n * d_in
* @param xt output vectors, size n * d_out
*/
virtual void apply_noalloc(size_t n, const float* x, float* xt) const = 0;
virtual void apply_noalloc(bigidx_t n, const float* x, float* xt) const = 0;

/// reverse transformation. May not be implemented or may return
/// approximate result
virtual void reverse_transform(size_t n, const float* xt, float* x) const;
virtual void reverse_transform(bigidx_t n, const float* xt, float* x) const;

// check that the two transforms are identical (to merge indexes)
virtual void check_identical(const VectorTransform& other) const = 0;
Expand Down Expand Up @@ -112,14 +114,14 @@ struct LinearTransform : VectorTransform {
bool have_bias = false);

/// same as apply, but result is pre-allocated
void apply_noalloc(size_t n, const float* x, float* xt) const override;
void apply_noalloc(bigidx_t n, const float* x, float* xt) const override;

/// compute x = A^T * (x - b)
/// is reverse transform if A has orthonormal lines
void transform_transpose(size_t n, const float* y, float* x) const;
void transform_transpose(bigidx_t n, const float* y, float* x) const;

/// works only if is_orthonormal
void reverse_transform(size_t n, const float* xt, float* x) const override;
void reverse_transform(bigidx_t n, const float* xt, float* x) const override;

/// compute A^T * A to set the is_orthonormal flag
void set_is_orthonormal();
Expand All @@ -146,7 +148,7 @@ struct RandomRotationMatrix : LinearTransform {
void init(int seed);

// initializes with an arbitrary seed
void train(size_t n, const float* x) override;
void train(bigidx_t n, const float* x) override;

RandomRotationMatrix() {}
};
Expand Down Expand Up @@ -192,7 +194,7 @@ struct PCAMatrix : LinearTransform {

/// train on n vectors. If n < d_in then the eigenvector matrix
/// will be completed with 0s
void train(size_t n, const float* x) override;
void train(bigidx_t n, const float* x) override;

/// copy pre-trained PCA matrix
void copy_from(const PCAMatrix& other);
Expand Down