Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e5de014
Refactor merge to call CAGRA's merge(), implement CAGRA prefiltering …
narangvivek10 Aug 15, 2025
8707048
Cagra to HNSW serialization and searching feature
narangvivek10 Aug 15, 2025
c69a568
Codec, format, reader, and writer separation
narangvivek10 Aug 18, 2025
6229769
Code refactoring - refinement, simplification, and cleanup.
narangvivek10 Aug 25, 2025
660cfc9
Versioning in Codecs, Formats, Readers, and Writers
narangvivek10 Aug 25, 2025
b9937fa
Rebase with latest cuvs-java
punAhuja Aug 28, 2025
953d093
Rebase with latest cuvs-java
Sep 1, 2025
5553e58
Multi-layer hnsw bug fix
narangvivek10 Sep 3, 2025
38e54ac
Update format names
narangvivek10 Sep 4, 2025
f26d455
Update pom.xml - remove dependencies.
narangvivek10 Sep 5, 2025
1a01a6c
Remove Jackson dependency and restricting commons-io to test only
chatman Sep 15, 2025
35c749d
Bump up the cuvs-java version
narangvivek10 Sep 16, 2025
49d690f
Adding fallback support and a test for it
narangvivek10 Sep 18, 2025
cc2913e
Code refactoring and cleanup
narangvivek10 Sep 18, 2025
333182f
Add a test and update the other
narangvivek10 Sep 19, 2025
0a4f7e0
Latest cuvs-java changes require cudart to be loaded manually
Sep 24, 2025
b51d76e
Using latest cuvs-java
Sep 24, 2025
b23d6ec
Merge branch 'branch-25.10' into searchscale/cagra-to-hnsw-serializat…
narangvivek10 Sep 25, 2025
fed1efb
Pin the libcuvs version
narangvivek10 Sep 25, 2025
dc7cc60
Update env yaml files
narangvivek10 Sep 25, 2025
a78dd29
Pin libcuvs version with variable version
narangvivek10 Sep 25, 2025
8ff4c40
Update update-version script to update libcuvs version in yaml files …
narangvivek10 Sep 25, 2025
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
4 changes: 4 additions & 0 deletions ci/release/update-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ sed_runner "s/VERSION=\".*\"/VERSION=\"${NEXT_FULL_JAVA_TAG}\"/g" build.sh
sed_runner "/<!--CUVS_LUCENE#VERSION_UPDATE_MARKER_START-->.*<!--CUVS_LUCENE#VERSION_UPDATE_MARKER_END-->/s//<!--CUVS_LUCENE#VERSION_UPDATE_MARKER_START--><version>${NEXT_FULL_JAVA_TAG}<\/version><!--CUVS_LUCENE#VERSION_UPDATE_MARKER_END-->/g" pom.xml

sed_runner "s| CuVS [[:digit:]]\{2\}\.[[:digit:]]\{2\} | CuVS ${NEXT_SHORT_TAG} |g" README.md

for FILE in dependencies.yaml conda/environments/*.yaml; do
sed_runner "s/libcuvs==.*/libcuvs==${NEXT_SHORT_TAG}.*/g" "${FILE}"
done
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
- libcuvs
- libcuvs==25.10.*
- maven
- openjdk=22.*
name: all_cuda-129_arch-aarch64
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
- libcuvs
- libcuvs==25.10.*
- maven
- openjdk=22.*
name: all_cuda-129_arch-x86_64
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-130_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
- libcuvs
- libcuvs==25.10.*
- maven
- openjdk=22.*
name: all_cuda-130_arch-aarch64
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-130_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
- libcuvs
- libcuvs==25.10.*
- maven
- openjdk=22.*
name: all_cuda-130_arch-x86_64
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
- libcuvs
- libcuvs==25.10.*
java:
common:
- output_types: conda
Expand Down
48 changes: 24 additions & 24 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<repositories>
<repository>
<id>cuvs-java</id>
<id>searchscale-maven</id>
<name>SearchScale Maven</name>
<url>https://maven.searchscale.com/snapshots</url>
</repository>
Expand All @@ -40,36 +40,17 @@
<version>10.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.15.1</version>
</dependency>
<dependency>
<groupId>com.github.fommil</groupId>
<artifactId>jniloader</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.17.0</version>
<version>2.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.nvidia.cuvs</groupId>
<artifactId>cuvs-java</artifactId>
<!-- Note: This is temporary measure (artifact coming from https://maven.searchscale.com/snapshots, for now) and will get updated in subsequent PRs. -->
<version>25.10.0-2c0e1-SNAPSHOT</version>
<!-- Note: This is a temporary measure (artifact coming from https://maven.searchscale.com/snapshots, for now) and will get updated in subsequent PRs. -->
<!--CUVS_LUCENE#VERSION_UPDATE_MARKER_START--><version>25.10.0</version><!--CUVS_LUCENE#VERSION_UPDATE_MARKER_END-->
</dependency>
</dependencies>

Expand Down Expand Up @@ -104,6 +85,25 @@
</java>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,57 @@
package com.nvidia.cuvs.lucene;

import com.nvidia.cuvs.LibraryException;
import com.nvidia.cuvs.lucene.CuVSVectorsWriter.IndexType;
import com.nvidia.cuvs.lucene.CuVS2510GPUVectorsWriter.IndexType;
import java.util.logging.Logger;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.lucene101.Lucene101Codec;

/** CuVS based codec for GPU based vector search */
public class CuVSCodec extends FilterCodec {
/** CuVS based codec for GPU based vector search
*
* @apiNote cuVS serialization formats are in experimental phase and hence backward compatibility cannot be guaranteed.
*
* */
public class CuVS2510GPUSearchCodec extends FilterCodec {

private static final Logger log = Logger.getLogger(CuVS2510GPUSearchCodec.class.getName());
private static final String NAME = "CuVS2510GPUSearchCodec";

public CuVSCodec() {
this("CuVSCodec", new Lucene101Codec());
private static final int DEFAULT_CUVS_WRITER_THREADS = 1;
private static final int DEFAULT_INTERMEDIATE_GRAPH_DEGREE = 128;
private static final int DEFAULT_GRAPH_DEGREE = 64;
private static final int DEFAULT_HNSW_LAYERS = 1;
private static final IndexType DEFAULT_INDEX_TYPE = IndexType.CAGRA;

private KnnVectorsFormat format;

public CuVS2510GPUSearchCodec() {
this(NAME, new Lucene101Codec());
}

public CuVSCodec(String name, Codec delegate) {
public CuVS2510GPUSearchCodec(String name, Codec delegate) {
super(name, delegate);
KnnVectorsFormat format;
try {
// TODO: Remove this hard coded values.
format = new CuVSVectorsFormat(1, 128, 64, IndexType.CAGRA);
format =
new CuVS2510GPUVectorsFormat(
DEFAULT_CUVS_WRITER_THREADS,
DEFAULT_INTERMEDIATE_GRAPH_DEGREE,
DEFAULT_GRAPH_DEGREE,
DEFAULT_HNSW_LAYERS,
DEFAULT_INDEX_TYPE);
setKnnFormat(format);
} catch (LibraryException ex) {
Logger log = Logger.getLogger(CuVSCodec.class.getName());
log.severe("Couldn't load native library, possible classloader issue. " + ex.getMessage());
}
}

KnnVectorsFormat knnFormat = null;

@Override
public KnnVectorsFormat knnVectorsFormat() {
return knnFormat;
return format;
}

public void setKnnFormat(KnnVectorsFormat format) {
this.knnFormat = format;
this.format = format;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,40 @@
*/
package com.nvidia.cuvs.lucene;

import static com.nvidia.cuvs.lucene.Utils.cuVSResourcesOrNull;

import com.nvidia.cuvs.CuVSResources;
import com.nvidia.cuvs.LibraryException;
import com.nvidia.cuvs.lucene.CuVSVectorsWriter.IndexType;
import com.nvidia.cuvs.lucene.CuVS2510GPUVectorsWriter.IndexType;
import java.io.IOException;
import java.util.logging.Logger;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.KnnVectorsReader;
import org.apache.lucene.codecs.hnsw.DefaultFlatVectorScorer;
import org.apache.lucene.codecs.hnsw.FlatVectorsFormat;
import org.apache.lucene.codecs.lucene99.Lucene99FlatVectorsFormat;
import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.SegmentWriteState;

/** CuVS based KnnVectorsFormat for GPU acceleration */
public class CuVSVectorsFormat extends KnnVectorsFormat {
public class CuVS2510GPUVectorsFormat extends KnnVectorsFormat {

private static final Logger LOG = Logger.getLogger(CuVSVectorsFormat.class.getName());
static final Logger log = Logger.getLogger(CuVS2510GPUVectorsFormat.class.getName());

// TODO: fix Lucene version in name, to the final targeted release, if any
static final String CUVS_META_CODEC_NAME = "Lucene102CuVSVectorsFormatMeta";
static final String CUVS_META_CODEC_EXT = "vemc"; // ""cagmf";
static final String CUVS_META_CODEC_EXT = "vemc";
static final String CUVS_INDEX_CODEC_NAME = "Lucene102CuVSVectorsFormatIndex";
static final String CUVS_INDEX_EXT = "vcag";

static final int VERSION_START = 0;
static final int VERSION_CURRENT = VERSION_START;

public static final int DEFAULT_WRITER_THREADS = 32;
public static final int DEFAULT_INTERMEDIATE_GRAPH_DEGREE = 128;
public static final int DEFAULT_GRAPH_DEGREE = 64;
public static final IndexType DEFAULT_INDEX_TYPE = IndexType.CAGRA;
static final int DEFAULT_WRITER_THREADS = 32;
static final int DEFAULT_INTERMEDIATE_GRAPH_DEGREE = 128;
static final int DEFAULT_GRAPH_DEGREE = 64;
static final IndexType DEFAULT_INDEX_TYPE = IndexType.CAGRA;
static final int HNSW_GRAPH_LAYERS = 1;

static CuVSResources resources = cuVSResourcesOrNull();

Expand All @@ -56,80 +60,61 @@ public class CuVSVectorsFormat extends KnnVectorsFormat {
final int cuvsWriterThreads;
final int intGraphDegree;
final int graphDegree;
final CuVSVectorsWriter.IndexType indexType; // the index type to build, when writing
final int hnswLayers; // Number of layers to create in CAGRA->HNSW conversion
final CuVS2510GPUVectorsWriter.IndexType indexType; // the index type to build, when writing

/**
* Creates a CuVSVectorsFormat, with default values.
* Creates a CuVS2510GPUVectorsFormat, with default values.
*
* @throws LibraryException if the native library fails to load
*/
public CuVSVectorsFormat() {
public CuVS2510GPUVectorsFormat() {
this(
DEFAULT_WRITER_THREADS,
DEFAULT_INTERMEDIATE_GRAPH_DEGREE,
DEFAULT_GRAPH_DEGREE,
HNSW_GRAPH_LAYERS,
DEFAULT_INDEX_TYPE);
}

/**
* Creates a CuVSVectorsFormat, with the given threads, graph degree, etc.
* Creates a CuVS2510GPUVectorsFormat, with the given threads, graph degree, etc.
*
* @throws LibraryException if the native library fails to load
*/
public CuVSVectorsFormat(
int cuvsWriterThreads, int intGraphDegree, int graphDegree, IndexType indexType) {
super("CuVSVectorsFormat");
public CuVS2510GPUVectorsFormat(
int cuvsWriterThreads,
int intGraphDegree,
int graphDegree,
int hnswLayers,
IndexType indexType) {
super("CuVS2510GPUVectorsFormat");
this.cuvsWriterThreads = cuvsWriterThreads;
this.intGraphDegree = intGraphDegree;
this.graphDegree = graphDegree;
this.hnswLayers = hnswLayers;
this.indexType = indexType;
}

private static CuVSResources cuVSResourcesOrNull() {
try {
System.loadLibrary(
"cudart"); // nocommit: this is here so as to pass CI, should goto cuvs-java
} catch (UnsatisfiedLinkError e) {
LOG.warning("Could not load CUDA runtime library: " + e.getMessage());
}
try {
resources = CuVSResources.create();
return resources;
} catch (UnsupportedOperationException uoe) {
LOG.warning("cuvs is not supported on this platform or java version: " + uoe.getMessage());
} catch (Throwable t) {
if (t instanceof ExceptionInInitializerError ex) {
t = ex.getCause();
}
LOG.warning("Exception occurred during creation of cuvs resources. " + t);
}
return null;
}

/** Tells whether the platform supports cuvs. */
public static boolean supported() {
return resources != null;
}

private static void checkSupported() {
if (!supported()) {
throw new UnsupportedOperationException();
}
}

@Override
public CuVSVectorsWriter fieldsWriter(SegmentWriteState state) throws IOException {
public CuVS2510GPUVectorsWriter fieldsWriter(SegmentWriteState state) throws IOException {
checkSupported();
var flatWriter = flatVectorsFormat.fieldsWriter(state);
return new CuVSVectorsWriter(
state, cuvsWriterThreads, intGraphDegree, graphDegree, indexType, resources, flatWriter);
return new CuVS2510GPUVectorsWriter(
state,
cuvsWriterThreads,
intGraphDegree,
graphDegree,
hnswLayers,
indexType,
resources,
flatWriter);
}

@Override
public CuVSVectorsReader fieldsReader(SegmentReadState state) throws IOException {
public KnnVectorsReader fieldsReader(SegmentReadState state) throws IOException {
checkSupported();
var flatReader = flatVectorsFormat.fieldsReader(state);
return new CuVSVectorsReader(state, resources, flatReader);
return new CuVS2510GPUVectorsReader(state, resources, flatVectorsFormat.fieldsReader(state));
}

@Override
Expand All @@ -139,12 +124,24 @@ public int getMaxDimensions(String fieldName) {

@Override
public String toString() {
StringBuilder sb = new StringBuilder("CuVSVectorsFormat(");
sb.append("cuvsWriterThreads=").append(cuvsWriterThreads);
StringBuilder sb = new StringBuilder(this.getClass().getSimpleName());
sb.append("(cuvsWriterThreads=").append(cuvsWriterThreads);
sb.append("intGraphDegree=").append(intGraphDegree);
sb.append("graphDegree=").append(graphDegree);
sb.append("hnswLayers=").append(hnswLayers);
sb.append("resources=").append(resources);
sb.append(")");
return sb.toString();
}

/** Tells whether the platform supports cuVS. */
public static boolean supported() {
return resources != null;
}

public static void checkSupported() {
if (!supported()) {
throw new UnsupportedOperationException();
}
}
}
Loading