Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Kane
8b0443afdf Test sparsevec vacuum recall 2024-04-23 17:10:48 -07:00
11 changed files with 28 additions and 155 deletions

View File

@@ -1,31 +1,15 @@
name: build name: build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
ubuntu: valgrind:
runs-on: ${{ matrix.os }}
if: ${{ !startsWith(github.ref_name, 'mac') && !startsWith(github.ref_name, 'windows') }} if: ${{ !startsWith(github.ref_name, 'mac') && !startsWith(github.ref_name, 'windows') }}
strategy: runs-on: ubuntu-latest
fail-fast: false
matrix:
include:
- postgres: 14
os: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ankane/setup-postgres@v1 - uses: ankane/setup-postgres-valgrind@v1
with: with:
postgres-version: ${{ matrix.postgres }} postgres-version: 16
dev-files: true check-ub: yes
- run: make - run: make OPTFLAGS=""
env: - run: sudo --preserve-env=PG_CONFIG make install
PG_CFLAGS: -DUSE_ASSERT_CHECKING -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare - run: make prove_installcheck PROVE_TESTS=test/t/031_hnsw_sparsevec_vacuum_recall.pl
- run: |
export PG_CONFIG=`which pg_config`
sudo --preserve-env=PG_CONFIG make install
- run: make installcheck
- if: ${{ failure() }}
run: cat regression.diffs
- run: |
sudo apt-get update
sudo apt-get install libipc-run-perl
- run: for run in {1..100}; do make prove_installcheck PROVE_TESTS=test/t/031_hnsw_sparsevec_vacuum_recall.pl || break; done

View File

@@ -683,7 +683,7 @@ SparsevecL2SquaredDistance(SparseVector * a, SparseVector * b)
if (ai == bi) if (ai == bi)
{ {
float diff = ax[i] - bx[j]; double diff = ax[i] - bx[j];
distance += diff * diff; distance += diff * diff;
} }
@@ -721,7 +721,7 @@ sparsevec_l2_distance(PG_FUNCTION_ARGS)
CheckDims(a, b); CheckDims(a, b);
PG_RETURN_FLOAT8(sqrt((double) SparsevecL2SquaredDistance(a, b))); PG_RETURN_FLOAT8(sqrt(SparsevecL2SquaredDistance(a, b)));
} }
/* /*
@@ -737,7 +737,7 @@ sparsevec_l2_squared_distance(PG_FUNCTION_ARGS)
CheckDims(a, b); CheckDims(a, b);
PG_RETURN_FLOAT8((double) SparsevecL2SquaredDistance(a, b)); PG_RETURN_FLOAT8(SparsevecL2SquaredDistance(a, b));
} }
/* /*
@@ -788,7 +788,7 @@ sparsevec_inner_product(PG_FUNCTION_ARGS)
CheckDims(a, b); CheckDims(a, b);
PG_RETURN_FLOAT8((double) SparsevecInnerProduct(a, b)); PG_RETURN_FLOAT8(SparsevecInnerProduct(a, b));
} }
/* /*
@@ -803,7 +803,7 @@ sparsevec_negative_inner_product(PG_FUNCTION_ARGS)
CheckDims(a, b); CheckDims(a, b);
PG_RETURN_FLOAT8((double) -SparsevecInnerProduct(a, b)); PG_RETURN_FLOAT8(-SparsevecInnerProduct(a, b));
} }
/* /*
@@ -862,7 +862,7 @@ sparsevec_l1_distance(PG_FUNCTION_ARGS)
SparseVector *b = PG_GETARG_SPARSEVEC_P(1); SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
float *ax = SPARSEVEC_VALUES(a); float *ax = SPARSEVEC_VALUES(a);
float *bx = SPARSEVEC_VALUES(b); float *bx = SPARSEVEC_VALUES(b);
float distance = 0.0; double distance = 0.0;
int bpos = 0; int bpos = 0;
CheckDims(a, b); CheckDims(a, b);
@@ -897,7 +897,7 @@ sparsevec_l1_distance(PG_FUNCTION_ARGS)
for (int j = bpos; j < b->nnz; j++) for (int j = bpos; j < b->nnz; j++)
distance += fabsf(bx[j]); distance += fabsf(bx[j]);
PG_RETURN_FLOAT8((double) distance); PG_RETURN_FLOAT8(distance);
} }
/* /*

View File

@@ -3,38 +3,25 @@
#include "fmgr.h" #include "fmgr.h"
#define SPARSEVEC_MAX_DIM 1000000 #define SPARSEVEC_MAX_DIM 100000
#define SPARSEVEC_MAX_NNZ 16000 #define SPARSEVEC_MAX_NNZ 16000
/* Ensure values are aligned */
#define SPARSEVEC_SIZE(_nnz) (offsetof(SparseVector, indices) + MAXALIGN((_nnz) * sizeof(int32)) + (_nnz * sizeof(float)))
#define SPARSEVEC_VALUES(x) ((float *) (((char *) (x)) + offsetof(SparseVector, indices) + MAXALIGN((x)->nnz * sizeof(int32))))
#define DatumGetSparseVector(x) ((SparseVector *) PG_DETOAST_DATUM(x)) #define DatumGetSparseVector(x) ((SparseVector *) PG_DETOAST_DATUM(x))
#define PG_GETARG_SPARSEVEC_P(x) DatumGetSparseVector(PG_GETARG_DATUM(x)) #define PG_GETARG_SPARSEVEC_P(x) DatumGetSparseVector(PG_GETARG_DATUM(x))
#define PG_RETURN_SPARSEVEC_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_SPARSEVEC_P(x) PG_RETURN_POINTER(x)
/* Indices are always sorted */
/* Values come after indices */
typedef struct SparseVector typedef struct SparseVector
{ {
int32 vl_len_; /* varlena header (do not touch directly!) */ int32 vl_len_; /* varlena header (do not touch directly!) */
int32 dim; /* number of dimensions */ int32 dim; /* number of dimensions */
int32 nnz; /* number of non-zero elements */ int32 nnz;
int32 unused; int32 unused;
int32 indices[FLEXIBLE_ARRAY_MEMBER]; int32 indices[FLEXIBLE_ARRAY_MEMBER];
} SparseVector; } SparseVector;
/* Use functions instead of macros to avoid double evaluation */
static inline Size
SPARSEVEC_SIZE(int nnz)
{
return offsetof(SparseVector, indices) + (nnz * sizeof(int32)) + (nnz * sizeof(float));
}
static inline float *
SPARSEVEC_VALUES(SparseVector * x)
{
return (float *) (((char *) x) + offsetof(SparseVector, indices) + (x->nnz * sizeof(int32)));
}
SparseVector *InitSparseVector(int dim, int nnz); SparseVector *InitSparseVector(int dim, int nnz);
#endif #endif

View File

@@ -176,18 +176,6 @@ SELECT l2_norm('[0,1]'::halfvec);
1 1
(1 row) (1 row)
SELECT l2_norm('[0,0]'::halfvec);
l2_norm
---------
0
(1 row)
SELECT l2_norm('[2]'::halfvec);
l2_norm
---------
2
(1 row)
SELECT l2_distance('[0,0]'::halfvec, '[3,4]'); SELECT l2_distance('[0,0]'::halfvec, '[3,4]');
l2_distance l2_distance
------------- -------------

View File

@@ -136,18 +136,6 @@ SELECT l2_norm('{1:3e37,2:4e37}/2'::sparsevec)::real;
5e+37 5e+37
(1 row) (1 row)
SELECT l2_norm('{}/2'::sparsevec);
l2_norm
---------
0
(1 row)
SELECT l2_norm('{1:2}/1'::sparsevec);
l2_norm
---------
2
(1 row)
SELECT l2_distance('{}/2'::sparsevec, '{1:3,2:4}/2'); SELECT l2_distance('{}/2'::sparsevec, '{1:3,2:4}/2');
l2_distance l2_distance
------------- -------------
@@ -166,12 +154,6 @@ SELECT l2_distance('{2:4}/2'::sparsevec, '{1:3}/2');
5 5
(1 row) (1 row)
SELECT l2_distance('{1:3,2:4}/2'::sparsevec, '{}/2');
l2_distance
-------------
5
(1 row)
SELECT l2_distance('{}/2'::sparsevec, '{2:1}/2'); SELECT l2_distance('{}/2'::sparsevec, '{2:1}/2');
l2_distance l2_distance
------------- -------------
@@ -192,36 +174,6 @@ SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:2,2:4}/2');
SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:3}/1'); SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:3}/1');
ERROR: different sparsevec dimensions 2 and 1 ERROR: different sparsevec dimensions 2 and 1
SELECT inner_product('{1:1,3:3}/4'::sparsevec, '{2:2,4:4}/4');
inner_product
---------------
0
(1 row)
SELECT inner_product('{2:2,4:4}/4'::sparsevec, '{1:1,3:3}/4');
inner_product
---------------
0
(1 row)
SELECT inner_product('{1:1,3:3,5:5}/5'::sparsevec, '{2:4,3:6,4:8}/5');
inner_product
---------------
18
(1 row)
SELECT inner_product('{1:1}/2'::sparsevec, '{}/2');
inner_product
---------------
0
(1 row)
SELECT inner_product('{}/2'::sparsevec, '{1:1}/2');
inner_product
---------------
0
(1 row)
SELECT inner_product('{1:3e38}/1'::sparsevec, '{1:3e38}/1'); SELECT inner_product('{1:3e38}/1'::sparsevec, '{1:3e38}/1');
inner_product inner_product
--------------- ---------------
@@ -276,12 +228,6 @@ SELECT cosine_distance('{1:2}/2'::sparsevec, '{2:2}/2');
1 1
(1 row) (1 row)
SELECT cosine_distance('{2:2}/2'::sparsevec, '{1:2}/2');
cosine_distance
-----------------
1
(1 row)
SELECT cosine_distance('{1:1,2:2}/2'::sparsevec, '{1:3}/1'); SELECT cosine_distance('{1:1,2:2}/2'::sparsevec, '{1:3}/1');
ERROR: different sparsevec dimensions 2 and 1 ERROR: different sparsevec dimensions 2 and 1
SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:1.1,2:1.1}/2'); SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:1.1,2:1.1}/2');
@@ -346,12 +292,6 @@ SELECT l1_distance('{1:1,3:3,5:5,7:7,9:9}/9'::sparsevec, '{2:2,4:4,6:6,8:8}/9');
45 45
(1 row) (1 row)
SELECT '{}/2'::sparsevec <+> '{1:3,2:4}/2';
?column?
----------
7
(1 row)
SELECT l2_normalize('{1:3,2:4}/2'::sparsevec); SELECT l2_normalize('{1:3,2:4}/2'::sparsevec);
l2_normalize l2_normalize
----------------- -----------------

View File

@@ -187,9 +187,9 @@ SELECT '{}/-1'::sparsevec;
ERROR: sparsevec must have at least 1 dimension ERROR: sparsevec must have at least 1 dimension
LINE 1: SELECT '{}/-1'::sparsevec; LINE 1: SELECT '{}/-1'::sparsevec;
^ ^
SELECT '{}/1000001'::sparsevec; SELECT '{}/100001'::sparsevec;
ERROR: sparsevec cannot have more than 1000000 dimensions ERROR: sparsevec cannot have more than 100000 dimensions
LINE 1: SELECT '{}/1000001'::sparsevec; LINE 1: SELECT '{}/100001'::sparsevec;
^ ^
SELECT '{0:1}/1'::sparsevec; SELECT '{0:1}/1'::sparsevec;
ERROR: index "0" is out of range for type sparsevec ERROR: index "0" is out of range for type sparsevec
@@ -219,7 +219,7 @@ SELECT '{}/3'::sparsevec(0);
ERROR: dimensions for type sparsevec must be at least 1 ERROR: dimensions for type sparsevec must be at least 1
LINE 1: SELECT '{}/3'::sparsevec(0); LINE 1: SELECT '{}/3'::sparsevec(0);
^ ^
SELECT '{}/3'::sparsevec(1000001); SELECT '{}/3'::sparsevec(100001);
ERROR: dimensions for type sparsevec cannot exceed 1000000 ERROR: dimensions for type sparsevec cannot exceed 100000
LINE 1: SELECT '{}/3'::sparsevec(1000001); LINE 1: SELECT '{}/3'::sparsevec(100001);
^ ^

View File

@@ -182,18 +182,6 @@ SELECT vector_norm('[3e37,4e37]')::real;
5e+37 5e+37
(1 row) (1 row)
SELECT vector_norm('[0,0]');
vector_norm
-------------
0
(1 row)
SELECT vector_norm('[2]');
vector_norm
-------------
2
(1 row)
SELECT l2_distance('[0,0]'::vector, '[3,4]'); SELECT l2_distance('[0,0]'::vector, '[3,4]');
l2_distance l2_distance
------------- -------------

View File

@@ -40,8 +40,6 @@ SELECT vector_dims('[1,2,3]'::halfvec);
SELECT round(l2_norm('[1,1]'::halfvec)::numeric, 5); SELECT round(l2_norm('[1,1]'::halfvec)::numeric, 5);
SELECT l2_norm('[3,4]'::halfvec); SELECT l2_norm('[3,4]'::halfvec);
SELECT l2_norm('[0,1]'::halfvec); SELECT l2_norm('[0,1]'::halfvec);
SELECT l2_norm('[0,0]'::halfvec);
SELECT l2_norm('[2]'::halfvec);
SELECT l2_distance('[0,0]'::halfvec, '[3,4]'); SELECT l2_distance('[0,0]'::halfvec, '[3,4]');
SELECT l2_distance('[0,0]'::halfvec, '[0,1]'); SELECT l2_distance('[0,0]'::halfvec, '[0,1]');

View File

@@ -23,23 +23,15 @@ SELECT round(l2_norm('{1:1,2:1}/2'::sparsevec)::numeric, 5);
SELECT l2_norm('{1:3,2:4}/2'::sparsevec); SELECT l2_norm('{1:3,2:4}/2'::sparsevec);
SELECT l2_norm('{2:1}/2'::sparsevec); SELECT l2_norm('{2:1}/2'::sparsevec);
SELECT l2_norm('{1:3e37,2:4e37}/2'::sparsevec)::real; SELECT l2_norm('{1:3e37,2:4e37}/2'::sparsevec)::real;
SELECT l2_norm('{}/2'::sparsevec);
SELECT l2_norm('{1:2}/1'::sparsevec);
SELECT l2_distance('{}/2'::sparsevec, '{1:3,2:4}/2'); SELECT l2_distance('{}/2'::sparsevec, '{1:3,2:4}/2');
SELECT l2_distance('{1:3}/2'::sparsevec, '{2:4}/2'); SELECT l2_distance('{1:3}/2'::sparsevec, '{2:4}/2');
SELECT l2_distance('{2:4}/2'::sparsevec, '{1:3}/2'); SELECT l2_distance('{2:4}/2'::sparsevec, '{1:3}/2');
SELECT l2_distance('{1:3,2:4}/2'::sparsevec, '{}/2');
SELECT l2_distance('{}/2'::sparsevec, '{2:1}/2'); SELECT l2_distance('{}/2'::sparsevec, '{2:1}/2');
SELECT '{}/2'::sparsevec <-> '{1:3,2:4}/2'; SELECT '{}/2'::sparsevec <-> '{1:3,2:4}/2';
SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:2,2:4}/2'); SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:2,2:4}/2');
SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:3}/1'); SELECT inner_product('{1:1,2:2}/2'::sparsevec, '{1:3}/1');
SELECT inner_product('{1:1,3:3}/4'::sparsevec, '{2:2,4:4}/4');
SELECT inner_product('{2:2,4:4}/4'::sparsevec, '{1:1,3:3}/4');
SELECT inner_product('{1:1,3:3,5:5}/5'::sparsevec, '{2:4,3:6,4:8}/5');
SELECT inner_product('{1:1}/2'::sparsevec, '{}/2');
SELECT inner_product('{}/2'::sparsevec, '{1:1}/2');
SELECT inner_product('{1:3e38}/1'::sparsevec, '{1:3e38}/1'); SELECT inner_product('{1:3e38}/1'::sparsevec, '{1:3e38}/1');
SELECT inner_product('{1:1,3:3,5:5}/5'::sparsevec, '{2:4,3:6,4:8}/5'); SELECT inner_product('{1:1,3:3,5:5}/5'::sparsevec, '{2:4,3:6,4:8}/5');
SELECT '{1:1,2:2}/2'::sparsevec <#> '{1:3,2:4}/2'; SELECT '{1:1,2:2}/2'::sparsevec <#> '{1:3,2:4}/2';
@@ -50,7 +42,6 @@ SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:1,2:1}/2');
SELECT cosine_distance('{1:1}/2'::sparsevec, '{2:2}/2'); SELECT cosine_distance('{1:1}/2'::sparsevec, '{2:2}/2');
SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:-1,2:-1}/2'); SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:-1,2:-1}/2');
SELECT cosine_distance('{1:2}/2'::sparsevec, '{2:2}/2'); SELECT cosine_distance('{1:2}/2'::sparsevec, '{2:2}/2');
SELECT cosine_distance('{2:2}/2'::sparsevec, '{1:2}/2');
SELECT cosine_distance('{1:1,2:2}/2'::sparsevec, '{1:3}/1'); SELECT cosine_distance('{1:1,2:2}/2'::sparsevec, '{1:3}/1');
SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:1.1,2:1.1}/2'); SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:1.1,2:1.1}/2');
SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:-1.1,2:-1.1}/2'); SELECT cosine_distance('{1:1,2:1}/2'::sparsevec, '{1:-1.1,2:-1.1}/2');
@@ -64,7 +55,6 @@ SELECT l1_distance('{1:1,2:2}/2'::sparsevec, '{1:3}/1');
SELECT l1_distance('{1:3e38}/1'::sparsevec, '{1:-3e38}/1'); SELECT l1_distance('{1:3e38}/1'::sparsevec, '{1:-3e38}/1');
SELECT l1_distance('{1:1,3:3,5:5,7:7}/8'::sparsevec, '{2:2,4:4,6:6,8:8}/8'); SELECT l1_distance('{1:1,3:3,5:5,7:7}/8'::sparsevec, '{2:2,4:4,6:6,8:8}/8');
SELECT l1_distance('{1:1,3:3,5:5,7:7,9:9}/9'::sparsevec, '{2:2,4:4,6:6,8:8}/9'); SELECT l1_distance('{1:1,3:3,5:5,7:7,9:9}/9'::sparsevec, '{2:2,4:4,6:6,8:8}/9');
SELECT '{}/2'::sparsevec <+> '{1:3,2:4}/2';
SELECT l2_normalize('{1:3,2:4}/2'::sparsevec); SELECT l2_normalize('{1:3,2:4}/2'::sparsevec);
SELECT l2_normalize('{1:3}/2'::sparsevec); SELECT l2_normalize('{1:3}/2'::sparsevec);

View File

@@ -38,7 +38,7 @@ SELECT '{1:1,1:1}/2'::sparsevec;
SELECT '{1:1,2:1,1:1}/2'::sparsevec; SELECT '{1:1,2:1,1:1}/2'::sparsevec;
SELECT '{}/5'::sparsevec; SELECT '{}/5'::sparsevec;
SELECT '{}/-1'::sparsevec; SELECT '{}/-1'::sparsevec;
SELECT '{}/1000001'::sparsevec; SELECT '{}/100001'::sparsevec;
SELECT '{0:1}/1'::sparsevec; SELECT '{0:1}/1'::sparsevec;
SELECT '{2:1}/1'::sparsevec; SELECT '{2:1}/1'::sparsevec;
@@ -47,4 +47,4 @@ SELECT '{}/3'::sparsevec(2);
SELECT '{}/3'::sparsevec(3, 2); SELECT '{}/3'::sparsevec(3, 2);
SELECT '{}/3'::sparsevec('a'); SELECT '{}/3'::sparsevec('a');
SELECT '{}/3'::sparsevec(0); SELECT '{}/3'::sparsevec(0);
SELECT '{}/3'::sparsevec(1000001); SELECT '{}/3'::sparsevec(100001);

View File

@@ -41,8 +41,6 @@ SELECT round(vector_norm('[1,1]')::numeric, 5);
SELECT vector_norm('[3,4]'); SELECT vector_norm('[3,4]');
SELECT vector_norm('[0,1]'); SELECT vector_norm('[0,1]');
SELECT vector_norm('[3e37,4e37]')::real; SELECT vector_norm('[3e37,4e37]')::real;
SELECT vector_norm('[0,0]');
SELECT vector_norm('[2]');
SELECT l2_distance('[0,0]'::vector, '[3,4]'); SELECT l2_distance('[0,0]'::vector, '[3,4]');
SELECT l2_distance('[0,0]'::vector, '[0,1]'); SELECT l2_distance('[0,0]'::vector, '[0,1]');