Skip to content

Commit 4390d55

Browse files
Introduce an index level setting: index.vectors.indexing.use_gpu
index.vectors.indexing.use_gpu has 3 options: - auto (null) default: use gpu indexing when available - false: don't use gpu indexing - true: use gpu indexing and if not available, throw an error
1 parent 9f2c96f commit 4390d55

File tree

5 files changed

+93
-10
lines changed

5 files changed

+93
-10
lines changed

server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
246246
if (SYNTHETIC_VECTORS) {
247247
settings.add(IndexSettings.INDEX_MAPPING_SOURCE_SYNTHETIC_VECTORS_SETTING);
248248
}
249+
settings.add(IndexSettings.VECTORS_INDEXING_USE_GPU_SETTING);
249250
BUILT_IN_INDEX_SETTINGS = Collections.unmodifiableSet(settings);
250251
};
251252

server/src/main/java/org/elasticsearch/index/IndexSettings.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
* be called for each settings update.
6666
*/
6767
public final class IndexSettings {
68+
6869
public static final Setting<List<String>> DEFAULT_FIELD_SETTING = Setting.stringListSetting(
6970
"index.query.default_field",
7071
Collections.singletonList("*"),
@@ -856,6 +857,32 @@ private static String getIgnoreAboveDefaultValue(final Settings settings) {
856857
Property.Final
857858
);
858859

860+
/**
861+
* An enum for the tri-state value of the `index.vectors.indexing.use_gpu` setting.
862+
*/
863+
public enum GpuMode {
864+
TRUE,
865+
FALSE,
866+
AUTO
867+
}
868+
869+
/**
870+
* Setting to control whether to use GPU for vectors indexing.
871+
* Currently only applicable for index_options.type: hnsw.
872+
*
873+
* If unset or "auto", an automatic decision is made based on the presence of GPU, necessary libraries, vectors' count and dims.
874+
* If set to <code>true</code>, GPU must be used for vectors indexing, and if GPU or necessary libraries are not available,
875+
* an exception will be thrown.
876+
* If set to <code>false</code>, GPU will not be used for vectors indexing.
877+
*/
878+
public static final Setting<GpuMode> VECTORS_INDEXING_USE_GPU_SETTING = Setting.enumSetting(
879+
GpuMode.class,
880+
"index.vectors.indexing.use_gpu",
881+
GpuMode.AUTO,
882+
Property.IndexScope,
883+
Property.Dynamic
884+
);
885+
859886
private final Index index;
860887
private final IndexVersion version;
861888
private final Logger logger;
@@ -954,6 +981,8 @@ private void setRetentionLeaseMillis(final TimeValue retentionLease) {
954981
*/
955982
private volatile int maxSlicesPerScroll;
956983

984+
private volatile GpuMode useGpuForVectorsIndexing;
985+
957986
/**
958987
* The maximum length of regex string allowed in a regexp query.
959988
*/
@@ -1129,6 +1158,7 @@ public IndexSettings(final IndexMetadata indexMetadata, final Settings nodeSetti
11291158
&& scopedSettings.get(RECOVERY_USE_SYNTHETIC_SOURCE_SETTING);
11301159
useDocValuesSkipper = DOC_VALUES_SKIPPER && scopedSettings.get(USE_DOC_VALUES_SKIPPER);
11311160
seqNoIndexOptions = scopedSettings.get(SEQ_NO_INDEX_OPTIONS_SETTING);
1161+
this.useGpuForVectorsIndexing = scopedSettings.get(VECTORS_INDEXING_USE_GPU_SETTING);
11321162
if (recoverySourceSyntheticEnabled) {
11331163
if (DiscoveryNode.isStateless(settings)) {
11341164
throw new IllegalArgumentException("synthetic recovery source is only allowed in stateful");
@@ -1151,6 +1181,8 @@ public IndexSettings(final IndexMetadata indexMetadata, final Settings nodeSetti
11511181
}
11521182
}
11531183

1184+
scopedSettings.addSettingsUpdateConsumer(VECTORS_INDEXING_USE_GPU_SETTING, this::setUseGpuForVectorsIndexing);
1185+
11541186
scopedSettings.addSettingsUpdateConsumer(
11551187
MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING,
11561188
mergePolicyConfig::setCompoundFormatThreshold
@@ -1877,6 +1909,23 @@ private void setHnswEarlyTermination(boolean earlyTermination) {
18771909
this.earlyTermination = earlyTermination;
18781910
}
18791911

1912+
private void setUseGpuForVectorsIndexing(GpuMode useGpuForVectorsIndexing) {
1913+
this.useGpuForVectorsIndexing = useGpuForVectorsIndexing;
1914+
}
1915+
1916+
/**
1917+
* Whether to use GPU for vectors indexing.
1918+
* Currently only applicable for index_options.type: hnsw
1919+
*
1920+
* @return <code>GpuMode.TRUE</code> if GPU must be used for vectors indexing;
1921+
* <code>GpuMode.FALSE</code> if GPU will not be used, or
1922+
* <code>GpuMode.AUTO</code> if the setting is not set,
1923+
* meaning automatic decision is maded on the presence of GPU, libraries, vectors' count and dims.
1924+
*/
1925+
public GpuMode useGpuForVectorsIndexing() {
1926+
return useGpuForVectorsIndexing;
1927+
}
1928+
18801929
public SeqNoFieldMapper.SeqNoIndexOptions seqNoIndexOptions() {
18811930
return seqNoIndexOptions;
18821931
}

server/src/test/java/org/elasticsearch/index/IndexSettingsTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,4 +921,26 @@ public void testSame() {
921921
}
922922
assertTrue(IndexSettings.same(settings, differentOtherSettingBuilder.build()));
923923
}
924+
925+
public void testVectorsUseGpuSetting() {
926+
IndexMetadata metadata = newIndexMeta(
927+
"index",
928+
Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current()).build()
929+
);
930+
IndexSettings settings = new IndexSettings(metadata, Settings.EMPTY);
931+
assertEquals(IndexSettings.GpuMode.AUTO, settings.useGpuForVectorsIndexing());
932+
933+
settings.updateIndexMetadata(
934+
newIndexMeta("index", Settings.builder().put(IndexSettings.VECTORS_INDEXING_USE_GPU_SETTING.getKey(), true).build())
935+
);
936+
assertEquals(IndexSettings.GpuMode.TRUE, settings.useGpuForVectorsIndexing());
937+
938+
settings.updateIndexMetadata(
939+
newIndexMeta("index", Settings.builder().put(IndexSettings.VECTORS_INDEXING_USE_GPU_SETTING.getKey(), false).build())
940+
);
941+
assertEquals(IndexSettings.GpuMode.FALSE, settings.useGpuForVectorsIndexing());
942+
943+
settings.updateIndexMetadata(newIndexMeta("index", Settings.EMPTY));
944+
assertEquals(IndexSettings.GpuMode.AUTO, settings.useGpuForVectorsIndexing());
945+
}
924946
}

x-pack/plugin/gpu/src/main/java/org/elasticsearch/xpack/gpu/GPUPlugin.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
*/
77
package org.elasticsearch.xpack.gpu;
88

9+
import com.nvidia.cuvs.CuVSResources;
10+
911
import org.elasticsearch.common.util.FeatureFlag;
10-
import org.elasticsearch.index.mapper.vectors.DenseVectorFieldMapper;
12+
import org.elasticsearch.index.IndexSettings;
1113
import org.elasticsearch.index.mapper.vectors.VectorsFormatProvider;
1214
import org.elasticsearch.plugins.MapperPlugin;
1315
import org.elasticsearch.plugins.Plugin;
@@ -19,15 +21,24 @@ public class GPUPlugin extends Plugin implements MapperPlugin {
1921

2022
@Override
2123
public VectorsFormatProvider getVectorsFormatProvider() {
22-
// TODO check indexSettings if it allows for GPU indexing
2324
return (indexSettings, indexOptions) -> {
24-
if (GPU_FORMAT.isEnabled()
25-
&& GPUVectorsFormat.cuVSResourcesOrNull(false) != null
26-
&& indexOptions.getType() == DenseVectorFieldMapper.VectorIndexType.HNSW) {
27-
return new GPUVectorsFormat();
28-
} else {
29-
return null;
25+
if (GPU_FORMAT.isEnabled()) {
26+
IndexSettings.GpuMode gpuMode = indexSettings.getValue(IndexSettings.VECTORS_INDEXING_USE_GPU_SETTING);
27+
if (gpuMode == IndexSettings.GpuMode.TRUE) {
28+
CuVSResources resources = GPUVectorsFormat.cuVSResourcesOrNull(true);
29+
if (resources == null) {
30+
throw new IllegalArgumentException(
31+
"[index.vectors.indexing.use_gpu] was set to [true], but GPU resources are not accessible on the node."
32+
);
33+
} else {
34+
return new GPUVectorsFormat();
35+
}
36+
}
37+
if ((gpuMode == IndexSettings.GpuMode.AUTO) && GPUVectorsFormat.cuVSResourcesOrNull(false) != null) {
38+
return new GPUVectorsFormat();
39+
}
3040
}
41+
return null;
3142
};
3243
}
3344
}

x-pack/plugin/gpu/src/main/java/org/elasticsearch/xpack/gpu/codec/GPUVectorsFormat.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public GPUVectorsFormat() {
5656
public KnnVectorsWriter fieldsWriter(SegmentWriteState state) throws IOException {
5757
CuVSResources cuVSResources = cuVSResourcesOrNull(true);
5858
if (cuVSResources == null) {
59-
throw new IllegalArgumentException("GPU based vector search is not supported on this platform or java version");
59+
throw new IllegalArgumentException("GPU based vector indexing is not supported on this platform or java version");
6060
}
6161
return new GPUToHNSWVectorsWriter(
6262
cuVSResources,
@@ -95,7 +95,7 @@ public static CuVSResources cuVSResourcesOrNull(boolean logError) {
9595
} else {
9696
msg = ": " + uoe.getMessage();
9797
}
98-
LOG.warn("GPU based vector search is not supported on this platform or java version; " + msg);
98+
LOG.warn("GPU based vector indexing is not supported on this platform or java version; " + msg);
9999
}
100100
} catch (Throwable t) {
101101
if (logError) {

0 commit comments

Comments
 (0)