mirror of
https://github.com/pgvector/pgvector.git
synced 2026-06-06 05:51:21 +08:00
Added experimental support for Windows (including auto-vectorization) - closes #49
This commit is contained in:
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -42,3 +42,16 @@ jobs:
|
||||
wget -q https://github.com/postgres/postgres/archive/refs/tags/REL_14_5.tar.gz
|
||||
tar xf REL_14_5.tar.gz
|
||||
make prove_installcheck PROVE=prove PROVE_FLAGS="-I ./postgres-REL_14_5/src/test/perl" PERL5LIB="/Users/runner/perl5/lib/perl5"
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ankane/setup-postgres@v1
|
||||
with:
|
||||
postgres-version: 14
|
||||
- run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
nmake /NOLOGO /F Makefile.win
|
||||
nmake /NOLOGO /F Makefile.win install
|
||||
nmake /NOLOGO /F Makefile.win installcheck
|
||||
shell: cmd
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
- Changed text representation for vector elements to match `real`
|
||||
- Improved accuracy of text parsing for certain inputs
|
||||
- Added experimental support for Windows
|
||||
|
||||
## 0.3.2 (2022-11-22)
|
||||
|
||||
|
||||
65
Makefile.win
Normal file
65
Makefile.win
Normal file
@@ -0,0 +1,65 @@
|
||||
EXTENSION = vector
|
||||
EXTVERSION = 0.3.2
|
||||
|
||||
OBJS = src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\vector.obj
|
||||
|
||||
# For /arch flags
|
||||
# https://learn.microsoft.com/en-us/cpp/build/reference/arch-minimum-cpu-architecture
|
||||
OPTFLAGS =
|
||||
|
||||
# For auto-vectorization:
|
||||
# - MSVC (needs /O2 /fp:fast) - https://learn.microsoft.com/en-us/cpp/parallel/auto-parallelization-and-auto-vectorization?#auto-vectorizer
|
||||
PG_CFLAGS = $(PG_CFLAGS) $(OPTFLAGS) /O2 /fp:fast
|
||||
|
||||
# Debug MSVC auto-vectorization
|
||||
# https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/vectorizer-and-parallelizer-messages
|
||||
# PG_CFLAGS = $(PG_CFLAGS) /Qvec-report:2
|
||||
|
||||
all: sql\$(EXTENSION)--$(EXTVERSION).sql
|
||||
|
||||
sql\$(EXTENSION)--$(EXTVERSION).sql: sql\$(EXTENSION).sql
|
||||
copy sql\$(EXTENSION).sql $@
|
||||
|
||||
# TODO use pg_config
|
||||
INCLUDEDIR = $(PGROOT)\include
|
||||
INCLUDEDIR_SERVER = $(PGROOT)\include\server
|
||||
LIBDIR = $(PGROOT)\lib
|
||||
PKGLIBDIR = $(PGROOT)\lib
|
||||
SHAREDIR = $(PGROOT)\share
|
||||
|
||||
CFLAGS = /nologo /I"$(INCLUDEDIR_SERVER)\port\win32_msvc" /I"$(INCLUDEDIR_SERVER)\port\win32" /I"$(INCLUDEDIR_SERVER)" /I"$(INCLUDEDIR)"
|
||||
|
||||
CFLAGS = $(CFLAGS) $(PG_CFLAGS)
|
||||
|
||||
SHLIB = src\$(EXTENSION).dll
|
||||
|
||||
LIBS = "$(LIBDIR)\postgres.lib"
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) /c $< /Fo$@
|
||||
|
||||
$(SHLIB): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(OBJS) $(LIBS) /link /DLL /OUT:$(SHLIB)
|
||||
|
||||
all: $(SHLIB)
|
||||
|
||||
install:
|
||||
copy $(SHLIB) "$(PKGLIBDIR)"
|
||||
copy $(EXTENSION).control "$(SHAREDIR)\extension"
|
||||
copy sql\$(EXTENSION)--*.sql "$(SHAREDIR)\extension"
|
||||
|
||||
# TODO improve
|
||||
installcheck:
|
||||
createdb contrib_regression
|
||||
mkdir -p results
|
||||
psql -d contrib_regression -a -q -f test\sql\btree.sql > results\btree.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\cast.sql > results\cast.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\copy.sql > results\copy.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\functions.sql > results\functions.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\input.sql > results\input.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\ivfflat_cosine.sql > results\ivfflat_cosine.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\ivfflat_ip.sql > results\ivfflat_ip.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\ivfflat_l2.sql > results\ivfflat_l2.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\ivfflat_options.sql > results\ivfflat_options.out 2>&1
|
||||
psql -d contrib_regression -a -q -f test\sql\ivfflat_unlogged.sql > results\ivfflat_unlogged.out 2>&1
|
||||
cat results/*
|
||||
@@ -164,7 +164,7 @@ ivfflatvalidate(Oid opclassoid)
|
||||
*
|
||||
* See https://www.postgresql.org/docs/current/index-api.html
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(ivfflathandler);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflathandler);
|
||||
Datum
|
||||
ivfflathandler(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
/* Variables */
|
||||
extern int ivfflat_probes;
|
||||
|
||||
/* Exported functions */
|
||||
PGDLLEXPORT void _PG_init(void);
|
||||
|
||||
typedef struct VectorArrayData
|
||||
{
|
||||
int length;
|
||||
@@ -210,7 +213,6 @@ typedef IvfflatScanOpaqueData * IvfflatScanOpaque;
|
||||
#define VectorArraySet(_arr, _offset, _val) (memcpy(VECTOR_ARRAY_OFFSET(_arr, _offset), _val, VECTOR_SIZE(_arr->dim)))
|
||||
|
||||
/* Methods */
|
||||
void _PG_init(void);
|
||||
VectorArray VectorArrayInit(int maxlen, int dimensions);
|
||||
void VectorArrayFree(VectorArray arr);
|
||||
void PrintVectorArray(char *msg, VectorArray arr);
|
||||
|
||||
95
src/vector.c
95
src/vector.c
@@ -109,7 +109,7 @@ PrintVector(char *msg, Vector * vector)
|
||||
/*
|
||||
* Convert textual representation to internal representation
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_in);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_in);
|
||||
Datum
|
||||
vector_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -186,7 +186,7 @@ vector_in(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert internal representation to textual representation
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_out);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_out);
|
||||
Datum
|
||||
vector_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -247,7 +247,7 @@ vector_out(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert type modifier
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_typmod_in);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_typmod_in);
|
||||
Datum
|
||||
vector_typmod_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -278,7 +278,7 @@ vector_typmod_in(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert external binary representation to internal representation
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_recv);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_recv);
|
||||
Datum
|
||||
vector_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -310,7 +310,7 @@ vector_recv(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert internal representation to the external binary representation
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_send);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_send);
|
||||
Datum
|
||||
vector_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -330,7 +330,7 @@ vector_send(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert vector to vector
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector);
|
||||
Datum
|
||||
vector(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -345,7 +345,7 @@ vector(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert array to vector
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(array_to_vector);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(array_to_vector);
|
||||
Datum
|
||||
array_to_vector(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -403,7 +403,7 @@ array_to_vector(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Convert vector to float4[]
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_to_float4);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_float4);
|
||||
Datum
|
||||
vector_to_float4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -426,12 +426,14 @@ vector_to_float4(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the L2 distance between vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(l2_distance);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(l2_distance);
|
||||
Datum
|
||||
l2_distance(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
double distance = 0.0;
|
||||
double diff;
|
||||
|
||||
@@ -439,7 +441,7 @@ l2_distance(PG_FUNCTION_ARGS)
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
{
|
||||
diff = a->x[i] - b->x[i];
|
||||
diff = ax[i] - bx[i];
|
||||
distance += diff * diff;
|
||||
}
|
||||
|
||||
@@ -450,12 +452,14 @@ l2_distance(PG_FUNCTION_ARGS)
|
||||
* Get the L2 squared distance between vectors
|
||||
* This saves a sqrt calculation
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_l2_squared_distance);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_l2_squared_distance);
|
||||
Datum
|
||||
vector_l2_squared_distance(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
double distance = 0.0;
|
||||
double diff;
|
||||
|
||||
@@ -463,7 +467,7 @@ vector_l2_squared_distance(PG_FUNCTION_ARGS)
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
{
|
||||
diff = a->x[i] - b->x[i];
|
||||
diff = ax[i] - bx[i];
|
||||
distance += diff * diff;
|
||||
}
|
||||
|
||||
@@ -473,18 +477,20 @@ vector_l2_squared_distance(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the inner product of two vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(inner_product);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(inner_product);
|
||||
Datum
|
||||
inner_product(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
double distance = 0.0;
|
||||
|
||||
CheckDims(a, b);
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
distance += a->x[i] * b->x[i];
|
||||
distance += ax[i] * bx[i];
|
||||
|
||||
PG_RETURN_FLOAT8(distance);
|
||||
}
|
||||
@@ -492,18 +498,20 @@ inner_product(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the negative inner product of two vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_negative_inner_product);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_negative_inner_product);
|
||||
Datum
|
||||
vector_negative_inner_product(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
double distance = 0.0;
|
||||
|
||||
CheckDims(a, b);
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
distance += a->x[i] * b->x[i];
|
||||
distance += ax[i] * bx[i];
|
||||
|
||||
PG_RETURN_FLOAT8(distance * -1);
|
||||
}
|
||||
@@ -511,12 +519,14 @@ vector_negative_inner_product(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the cosine distance between two vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(cosine_distance);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(cosine_distance);
|
||||
Datum
|
||||
cosine_distance(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
double distance = 0.0;
|
||||
double norma = 0.0;
|
||||
double normb = 0.0;
|
||||
@@ -525,9 +535,9 @@ cosine_distance(PG_FUNCTION_ARGS)
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
{
|
||||
distance += a->x[i] * b->x[i];
|
||||
norma += a->x[i] * a->x[i];
|
||||
normb += b->x[i] * b->x[i];
|
||||
distance += ax[i] * bx[i];
|
||||
norma += ax[i] * ax[i];
|
||||
normb += bx[i] * bx[i];
|
||||
}
|
||||
|
||||
PG_RETURN_FLOAT8(1 - (distance / (sqrt(norma) * sqrt(normb))));
|
||||
@@ -538,7 +548,7 @@ cosine_distance(PG_FUNCTION_ARGS)
|
||||
* Currently uses angular distance since needs to satisfy triangle inequality
|
||||
* Assumes inputs are unit vectors (skips norm)
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_spherical_distance);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_spherical_distance);
|
||||
Datum
|
||||
vector_spherical_distance(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -563,7 +573,7 @@ vector_spherical_distance(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the dimensions of a vector
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_dims);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_dims);
|
||||
Datum
|
||||
vector_dims(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -575,15 +585,16 @@ vector_dims(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the L2 norm of a vector
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_norm);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_norm);
|
||||
Datum
|
||||
vector_norm(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
float *ax = a->x;
|
||||
double norm = 0.0;
|
||||
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
norm += a->x[i] * a->x[i];
|
||||
norm += ax[i] * ax[i];
|
||||
|
||||
PG_RETURN_FLOAT8(sqrt(norm));
|
||||
}
|
||||
@@ -591,20 +602,23 @@ vector_norm(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Add vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_add);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_add);
|
||||
Datum
|
||||
vector_add(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
Vector *result;
|
||||
int i;
|
||||
float *rx;
|
||||
|
||||
CheckDims(a, b);
|
||||
|
||||
result = InitVector(a->dim);
|
||||
for (i = 0; i < a->dim; i++)
|
||||
result->x[i] = a->x[i] + b->x[i];
|
||||
rx = result->x;
|
||||
for (int i = 0, imax = a->dim; i < imax; i++)
|
||||
rx[i] = ax[i] + bx[i];
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
}
|
||||
@@ -612,20 +626,23 @@ vector_add(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Subtract vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_sub);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_sub);
|
||||
Datum
|
||||
vector_sub(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Vector *a = PG_GETARG_VECTOR_P(0);
|
||||
Vector *b = PG_GETARG_VECTOR_P(1);
|
||||
float *ax = a->x;
|
||||
float *bx = b->x;
|
||||
Vector *result;
|
||||
int i;
|
||||
float *rx;
|
||||
|
||||
CheckDims(a, b);
|
||||
|
||||
result = InitVector(a->dim);
|
||||
for (i = 0; i < a->dim; i++)
|
||||
result->x[i] = a->x[i] - b->x[i];
|
||||
rx = result->x;
|
||||
for (int i = 0, imax = a->dim; i < imax; i++)
|
||||
rx[i] = ax[i] - bx[i];
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
}
|
||||
@@ -654,7 +671,7 @@ vector_cmp_internal(Vector * a, Vector * b)
|
||||
/*
|
||||
* Less than
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_lt);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_lt);
|
||||
Datum
|
||||
vector_lt(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -667,7 +684,7 @@ vector_lt(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Less than or equal
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_le);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_le);
|
||||
Datum
|
||||
vector_le(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -680,7 +697,7 @@ vector_le(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Equal
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_eq);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_eq);
|
||||
Datum
|
||||
vector_eq(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -693,7 +710,7 @@ vector_eq(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Not equal
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_ne);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_ne);
|
||||
Datum
|
||||
vector_ne(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -706,7 +723,7 @@ vector_ne(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Greater than or equal
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_ge);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_ge);
|
||||
Datum
|
||||
vector_ge(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -719,7 +736,7 @@ vector_ge(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Greater than
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_gt);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_gt);
|
||||
Datum
|
||||
vector_gt(PG_FUNCTION_ARGS)
|
||||
{
|
||||
@@ -732,7 +749,7 @@ vector_gt(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Compare vectors
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(vector_cmp);
|
||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_cmp);
|
||||
Datum
|
||||
vector_cmp(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user