Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Kane
17855c9861 Started Neon intrinsics [skip ci] 2024-04-27 22:50:47 -07:00
7 changed files with 95 additions and 75 deletions

View File

@@ -1,4 +1,4 @@
## 0.7.0 (2024-04-29) ## 0.7.0 (unreleased)
- Added `halfvec` type - Added `halfvec` type
- Added `sparsevec` type - Added `sparsevec` type

View File

@@ -2,7 +2,7 @@
"name": "vector", "name": "vector",
"abstract": "Open-source vector similarity search for Postgres", "abstract": "Open-source vector similarity search for Postgres",
"description": "Supports L2 distance, inner product, and cosine distance", "description": "Supports L2 distance, inner product, and cosine distance",
"version": "0.7.0", "version": "0.6.2",
"maintainer": [ "maintainer": [
"Andrew Kane <andrew@ankane.org>" "Andrew Kane <andrew@ankane.org>"
], ],
@@ -20,7 +20,7 @@
"vector": { "vector": {
"file": "sql/vector.sql", "file": "sql/vector.sql",
"docfile": "README.md", "docfile": "README.md",
"version": "0.7.0", "version": "0.6.2",
"abstract": "Open-source vector similarity search for Postgres" "abstract": "Open-source vector similarity search for Postgres"
} }
}, },

View File

@@ -1,5 +1,5 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.0 EXTVERSION = 0.6.2
MODULE_big = vector MODULE_big = vector
DATA = $(wildcard sql/*--*.sql) DATA = $(wildcard sql/*--*.sql)

View File

@@ -1,5 +1,5 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.0 EXTVERSION = 0.6.2
OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj
HEADERS = src\halfvec.h src\sparsevec.h src\vector.h HEADERS = src\halfvec.h src\sparsevec.h src\vector.h

135
README.md
View File

@@ -5,8 +5,7 @@ Open-source vector similarity search for Postgres
Store your vectors with the rest of your data. Supports: Store your vectors with the rest of your data. Supports:
- exact and approximate nearest neighbor search - exact and approximate nearest neighbor search
- single-precision, half-precision, binary, and sparse vectors - L2 distance, inner product, and cosine distance
- L2 distance, inner product, cosine distance, L1 distance, Hamming distance, and Jaccard distance
- any [language](#languages) with a Postgres client - any [language](#languages) with a Postgres client
Plus [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres Plus [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres
@@ -21,7 +20,7 @@ Compile and install the extension (supports Postgres 12+)
```sh ```sh
cd /tmp cd /tmp
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
make make
make install # may need sudo make install # may need sudo
@@ -46,7 +45,7 @@ Then use `nmake` to build:
```cmd ```cmd
set "PGROOT=C:\Program Files\PostgreSQL\16" set "PGROOT=C:\Program Files\PostgreSQL\16"
cd %TEMP% cd %TEMP%
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
nmake /F Makefile.win nmake /F Makefile.win
nmake /F Makefile.win install nmake /F Makefile.win install
@@ -82,7 +81,7 @@ Get the nearest neighbors by L2 distance
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
``` ```
Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, added in 0.7.0) Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, unreleased)
Note: `<#>` returns the negative inner product since Postgres only supports `ASC` order index scans on operators Note: `<#>` returns the negative inner product since Postgres only supports `ASC` order index scans on operators
@@ -144,7 +143,7 @@ Supported distance functions are:
- `<->` - L2 distance - `<->` - L2 distance
- `<#>` - (negative) inner product - `<#>` - (negative) inner product
- `<=>` - cosine distance - `<=>` - cosine distance
- `<+>` - L1 distance (added in 0.7.0) - `<+>` - L1 distance (unreleased)
Get the nearest neighbors to a row Get the nearest neighbors to a row
@@ -229,19 +228,19 @@ Cosine distance
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops); CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
``` ```
L1 distance - added in 0.7.0 L1 distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding vector_l1_ops); CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);
``` ```
Hamming distance - added in 0.7.0 Hamming distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops); CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);
``` ```
Jaccard distance - added in 0.7.0 Jaccard distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops); CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
@@ -250,9 +249,9 @@ CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
Supported types are: Supported types are:
- `vector` - up to 2,000 dimensions - `vector` - up to 2,000 dimensions
- `halfvec` - up to 4,000 dimensions (added in 0.7.0) - `halfvec` - up to 4,000 dimensions (unreleased)
- `bit` - up to 64,000 dimensions (added in 0.7.0) - `bit` - up to 64,000 dimensions (unreleased)
- `sparsevec` - up to 1,000 non-zero elements (added in 0.7.0) - `sparsevec` - up to 1,000 non-zero elements (unreleased)
### Index Options ### Index Options
@@ -357,7 +356,7 @@ Cosine distance
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
``` ```
Hamming distance - added in 0.7.0 Hamming distance - unreleased
```sql ```sql
CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100); CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100);
@@ -366,8 +365,8 @@ CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 10
Supported types are: Supported types are:
- `vector` - up to 2,000 dimensions - `vector` - up to 2,000 dimensions
- `halfvec` - up to 4,000 dimensions (added in 0.7.0) - `halfvec` - up to 4,000 dimensions (unreleased)
- `bit` - up to 64,000 dimensions (added in 0.7.0) - `bit` - up to 64,000 dimensions (unreleased)
### Query Options ### Query Options
@@ -441,9 +440,9 @@ Use [partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html
CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id); CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);
``` ```
## Half-Precision Vectors ## Half Vectors
*Added in 0.7.0* *Unreleased*
Use the `halfvec` type to store half-precision vectors Use the `halfvec` type to store half-precision vectors
@@ -451,9 +450,9 @@ Use the `halfvec` type to store half-precision vectors
CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3)); CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
``` ```
## Half-Precision Indexing ## Half Indexing
*Added in 0.7.0* *Unreleased*
Index vectors at half precision for smaller indexes and faster build times Index vectors at half precision for smaller indexes and faster build times
@@ -476,23 +475,23 @@ CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
INSERT INTO items (embedding) VALUES ('000'), ('111'); INSERT INTO items (embedding) VALUES ('000'), ('111');
``` ```
Get the nearest neighbors by Hamming distance (added in 0.7.0) Get the nearest neighbors by Hamming distance
```sql
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;
```
Or (before 0.7.0)
```sql ```sql
SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5; SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5;
``` ```
Or (unreleased)
```sql
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;
```
Also supports Jaccard distance (`<%>`) Also supports Jaccard distance (`<%>`)
## Binary Quantization ## Binary Quantization
*Added in 0.7.0* *Unreleased*
Use expression indexing for binary quantization Use expression indexing for binary quantization
@@ -516,7 +515,7 @@ SELECT * FROM (
## Sparse Vectors ## Sparse Vectors
*Added in 0.7.0* *Unreleased*
Use the `sparsevec` type to store sparse vectors Use the `sparsevec` type to store sparse vectors
@@ -551,7 +550,7 @@ You can use [Reciprocal Rank Fusion](https://github.com/pgvector/pgvector-python
## Indexing Subvectors ## Indexing Subvectors
*Added in 0.7.0* *Unreleased*
Use expression indexing to index subvectors Use expression indexing to index subvectors
@@ -865,23 +864,23 @@ Operator | Description | Added
\+ | element-wise addition | \+ | element-wise addition |
\- | element-wise subtraction | \- | element-wise subtraction |
\* | element-wise multiplication | 0.5.0 \* | element-wise multiplication | 0.5.0
\|\| | concatenate | 0.7.0 \|\| | concatenate | unreleased
<-> | Euclidean distance | <-> | Euclidean distance |
<#> | negative inner product | <#> | negative inner product |
<=> | cosine distance | <=> | cosine distance |
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Vector Functions ### Vector Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
binary_quantize(vector) → bit | binary quantize | 0.7.0 binary_quantize(vector) → bit | binary quantize | unreleased
cosine_distance(vector, vector) → double precision | cosine distance | cosine_distance(vector, vector) → double precision | cosine distance |
inner_product(vector, vector) → double precision | inner product | inner_product(vector, vector) → double precision | inner product |
l1_distance(vector, vector) → double precision | taxicab distance | 0.5.0 l1_distance(vector, vector) → double precision | taxicab distance | 0.5.0
l2_distance(vector, vector) → double precision | Euclidean distance | l2_distance(vector, vector) → double precision | Euclidean distance |
l2_normalize(vector) → vector | Normalize with Euclidean norm | 0.7.0 l2_normalize(vector) → vector | Normalize with Euclidean norm | unreleased
subvector(vector, integer, integer) → vector | subvector | 0.7.0 subvector(vector, integer, integer) → vector | subvector | unreleased
vector_dims(vector) → integer | number of dimensions | vector_dims(vector) → integer | number of dimensions |
vector_norm(vector) → double precision | Euclidean norm | vector_norm(vector) → double precision | Euclidean norm |
@@ -900,35 +899,35 @@ Each half vector takes `2 * dimensions + 8` bytes of storage. Each element is a
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
\+ | element-wise addition | 0.7.0 \+ | element-wise addition | unreleased
\- | element-wise subtraction | 0.7.0 \- | element-wise subtraction | unreleased
\* | element-wise multiplication | 0.7.0 \* | element-wise multiplication | unreleased
\|\| | concatenate | 0.7.0 \|\| | concatenate | unreleased
<-> | Euclidean distance | 0.7.0 <-> | Euclidean distance | unreleased
<#> | negative inner product | 0.7.0 <#> | negative inner product | unreleased
<=> | cosine distance | 0.7.0 <=> | cosine distance | unreleased
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Halfvec Functions ### Halfvec Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
binary_quantize(halfvec) → bit | binary quantize | 0.7.0 binary_quantize(halfvec) → bit | binary quantize | unreleased
cosine_distance(halfvec, halfvec) → double precision | cosine distance | 0.7.0 cosine_distance(halfvec, halfvec) → double precision | cosine distance | unreleased
inner_product(halfvec, halfvec) → double precision | inner product | 0.7.0 inner_product(halfvec, halfvec) → double precision | inner product | unreleased
l1_distance(halfvec, halfvec) → double precision | taxicab distance | 0.7.0 l1_distance(halfvec, halfvec) → double precision | taxicab distance | unreleased
l2_distance(halfvec, halfvec) → double precision | Euclidean distance | 0.7.0 l2_distance(halfvec, halfvec) → double precision | Euclidean distance | unreleased
l2_norm(halfvec) → double precision | Euclidean norm | 0.7.0 l2_norm(halfvec) → double precision | Euclidean norm | unreleased
l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | 0.7.0 l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | unreleased
subvector(halfvec, integer, integer) → halfvec | subvector | 0.7.0 subvector(halfvec, integer, integer) → halfvec | subvector | unreleased
vector_dims(halfvec) → integer | number of dimensions | 0.7.0 vector_dims(halfvec) → integer | number of dimensions | unreleased
### Halfvec Aggregate Functions ### Halfvec Aggregate Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
avg(halfvec) → halfvec | average | 0.7.0 avg(halfvec) → halfvec | average | unreleased
sum(halfvec) → halfvec | sum | 0.7.0 sum(halfvec) → halfvec | sum | unreleased
### Bit Type ### Bit Type
@@ -938,15 +937,15 @@ Each bit vector takes `dimensions / 8 + 8` bytes of storage. See the [Postgres d
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
<~> | Hamming distance | 0.7.0 <~> | Hamming distance | unreleased
<%> | Jaccard distance | 0.7.0 <%> | Jaccard distance | unreleased
### Bit Functions ### Bit Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
hamming_distance(bit, bit) → double precision | Hamming distance | 0.7.0 hamming_distance(bit, bit) → double precision | Hamming distance | unreleased
jaccard_distance(bit, bit) → double precision | Jaccard distance | 0.7.0 jaccard_distance(bit, bit) → double precision | Jaccard distance | unreleased
### Sparsevec Type ### Sparsevec Type
@@ -956,21 +955,21 @@ Each sparse vector takes `8 * non-zero elements + 16` bytes of storage. Each ele
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
<-> | Euclidean distance | 0.7.0 <-> | Euclidean distance | unreleased
<#> | negative inner product | 0.7.0 <#> | negative inner product | unreleased
<=> | cosine distance | 0.7.0 <=> | cosine distance | unreleased
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Sparsevec Functions ### Sparsevec Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | 0.7.0 cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | unreleased
inner_product(sparsevec, sparsevec) → double precision | inner product | 0.7.0 inner_product(sparsevec, sparsevec) → double precision | inner product | unreleased
l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | 0.7.0 l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | unreleased
l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | 0.7.0 l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | unreleased
l2_norm(sparsevec) → double precision | Euclidean norm | 0.7.0 l2_norm(sparsevec) → double precision | Euclidean norm | unreleased
l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | 0.7.0 l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | unreleased
## Installation Notes - Linux and Mac ## Installation Notes - Linux and Mac
@@ -1047,7 +1046,7 @@ This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres) (r
You can also build the image manually: You can also build the image manually:
```sh ```sh
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
docker build --build-arg PG_MAJOR=16 -t myuser/pgvector . docker build --build-arg PG_MAJOR=16 -t myuser/pgvector .
``` ```

View File

@@ -1,5 +1,7 @@
#include "postgres.h" #include "postgres.h"
#include <arm_neon.h>
#include "halfutils.h" #include "halfutils.h"
#include "halfvec.h" #include "halfvec.h"
@@ -28,9 +30,28 @@ static float
HalfvecL2SquaredDistanceDefault(int dim, half * ax, half * bx) HalfvecL2SquaredDistanceDefault(int dim, half * ax, half * bx)
{ {
float distance = 0.0; float distance = 0.0;
int i = 0;
/* TODO Improve */
#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
int count = (dim / 8) * 8;
float32x4_t dist = vmovq_n_f32(0);
for (; i < count; i += 8)
{
float16x8_t axs = vld1q_f16((const __fp16 *) (ax + i));
float16x8_t bxs = vld1q_f16((const __fp16 *) (bx + i));
float16x8_t diff = vsubq_f16(axs, bxs);
dist = vfmlalq_low_f16(dist, diff, diff);
dist = vfmlalq_high_f16(dist, diff, diff);
}
distance += vaddvq_f32(dist);
#endif
/* Auto-vectorized */ /* Auto-vectorized */
for (int i = 0; i < dim; i++) for (; i < dim; i++)
{ {
float diff = HalfToFloat4(ax[i]) - HalfToFloat4(bx[i]); float diff = HalfToFloat4(ax[i]) - HalfToFloat4(bx[i]);

View File

@@ -1,4 +1,4 @@
comment = 'vector data type and ivfflat and hnsw access methods' comment = 'vector data type and ivfflat and hnsw access methods'
default_version = '0.7.0' default_version = '0.6.2'
module_pathname = '$libdir/vector' module_pathname = '$libdir/vector'
relocatable = true relocatable = true