Skip to content

Commit

Permalink
Changed the default values for ef_search and ef_constrction for enabl…
Browse files Browse the repository at this point in the history
…ing better indexing and search latency for vector search

Signed-off-by: Navneet Verma <[email protected]>
  • Loading branch information
navneet1v committed Dec 10, 2023
1 parent 7c1782a commit 3a0e1ec
Show file tree
Hide file tree
Showing 26 changed files with 336 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

package org.opensearch.knn.bwc;

import org.junit.Assert;
import org.opensearch.knn.index.KNNSettings;

public class IndexSettingIT extends AbstractRestartUpgradeTestCase {
private static final String TEST_FIELD = "test-field";
private static final int DIMENSIONS = 5;

public void testOldIndexSettingsPersistedAfterUpgrade() throws Exception {
if (isRunningAgainstOldCluster()) {
// create index with Old Values
createKnnIndex(testIndex, getKNNDefaultIndexSettings(), createKnnIndexMapping(TEST_FIELD, DIMENSIONS));
int old_ef_search = Integer.parseInt(getIndexSettingByName(testIndex, KNNSettings.KNN_ALGO_PARAM_EF_SEARCH, true));
Assert.assertEquals(KNNSettings.INDEX_KNN_DEFAULT_ALGO_PARAM_EF_SEARCH.intValue(), old_ef_search);
} else {
int old_ef_search = Integer.parseInt(getIndexSettingByName(testIndex, KNNSettings.KNN_ALGO_PARAM_EF_SEARCH, true));
Assert.assertEquals(KNNSettings.INDEX_KNN_DEFAULT_ALGO_PARAM_EF_SEARCH.intValue(), old_ef_search);
deleteKNNIndex(testIndex);
}
}

// private void assertEfSearchOldDefaultValue(String indexName) {
// if (Version.fromString(getBWCVersion().get()).onOrAfter(Version.V_2_10_0)) {
//
// }
//
// }
}
1 change: 1 addition & 0 deletions src/main/java/org/opensearch/knn/common/KNNConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class KNNConstants {
// nmslib specific constants
public static final String NMSLIB_NAME = "nmslib";
public static final String SPACE_TYPE = "spaceType"; // used as field info key
public static final String VERSION = "version"; // used as field info key
public static final String HNSW_ALGO_M = "M";
public static final String HNSW_ALGO_EF_CONSTRUCTION = "efConstruction";
public static final String HNSW_ALGO_EF_SEARCH = "efSearch";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

package org.opensearch.knn.index;

import lombok.NoArgsConstructor;
import org.opensearch.common.settings.Settings;
import org.opensearch.index.shard.IndexSettingProvider;

@NoArgsConstructor
public class KNNIndexSettingProvider implements IndexSettingProvider {

private static final Settings EF_SEARCH_SETTING = Settings.builder()
.put(KNNSettings.KNN_ALGO_PARAM_EF_SEARCH, KNNSettings.INDEX_KNN_NEW_DEFAULT_ALGO_PARAM_EF_SEARCH)
.build();

/**
* Returns explicitly set default index {@link Settings} for the given index. This should not
* return null.
*
* @param indexName {@link String} name of the index
* @param isDataStreamIndex boolean: index is a datastream index or not
* @param templateAndRequestSettings {@link Settings}
*/
@Override
public Settings getAdditionalIndexSettings(String indexName, boolean isDataStreamIndex, Settings templateAndRequestSettings) {
if (isKNNIndex(templateAndRequestSettings) && isEfSearchNotSetByUser(templateAndRequestSettings)) {
return EF_SEARCH_SETTING;
}
return IndexSettingProvider.super.getAdditionalIndexSettings(indexName, isDataStreamIndex, templateAndRequestSettings);
}

private boolean isKNNIndex(Settings templateAndRequestSettings) {
return templateAndRequestSettings.getAsBoolean(KNNSettings.KNN_INDEX, false);
}

private boolean isEfSearchNotSetByUser(Settings templateAndRequestSettings) {
return templateAndRequestSettings.hasValue(KNNSettings.KNN_ALGO_PARAM_EF_SEARCH) == false;
}
}
8 changes: 4 additions & 4 deletions src/main/java/org/opensearch/knn/index/KNNMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public ValidationException validate(KNNMethodContext knnMethodContext) {
);
}

ValidationException methodValidation = methodComponent.validate(knnMethodContext.getMethodComponent());
ValidationException methodValidation = methodComponent.validate(knnMethodContext.getMethodComponentContext());
if (methodValidation != null) {
errorMessages.addAll(methodValidation.validationErrors());
}
Expand All @@ -84,7 +84,7 @@ public ValidationException validate(KNNMethodContext knnMethodContext) {
* @return true if training is required; false otherwise
*/
public boolean isTrainingRequired(KNNMethodContext knnMethodContext) {
return methodComponent.isTrainingRequired(knnMethodContext.getMethodComponent());
return methodComponent.isTrainingRequired(knnMethodContext.getMethodComponentContext());
}

/**
Expand All @@ -95,7 +95,7 @@ public boolean isTrainingRequired(KNNMethodContext knnMethodContext) {
* @return estimate overhead in KB
*/
public int estimateOverheadInKB(KNNMethodContext knnMethodContext, int dimension) {
return methodComponent.estimateOverheadInKB(knnMethodContext.getMethodComponent(), dimension);
return methodComponent.estimateOverheadInKB(knnMethodContext.getMethodComponentContext(), dimension);
}

/**
Expand All @@ -105,7 +105,7 @@ public int estimateOverheadInKB(KNNMethodContext knnMethodContext, int dimension
* @return KNNMethod as a map
*/
public Map<String, Object> getAsMap(KNNMethodContext knnMethodContext) {
Map<String, Object> parameterMap = new HashMap<>(methodComponent.getAsMap(knnMethodContext.getMethodComponent()));
Map<String, Object> parameterMap = new HashMap<>(methodComponent.getAsMap(knnMethodContext.getMethodComponentContext()));
parameterMap.put(KNNConstants.SPACE_TYPE, knnMethodContext.getSpaceType().getValue());
return parameterMap;
}
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/opensearch/knn/index/KNNMethodContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

package org.opensearch.knn.index;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.opensearch.common.ValidationException;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
Expand Down Expand Up @@ -41,7 +41,7 @@
* KNNMethodContext will contain the information necessary to produce a library index from an Opensearch mapping.
* It will encompass all parameters necessary to build the index.
*/
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
public class KNNMethodContext implements ToXContentFragment, Writeable {

Expand All @@ -63,7 +63,7 @@ public static synchronized KNNMethodContext getDefault() {
@NonNull
private final SpaceType spaceType;
@NonNull
private final MethodComponentContext methodComponent;
private final MethodComponentContext methodComponentContext;

/**
* Constructor from stream.
Expand All @@ -74,7 +74,7 @@ public static synchronized KNNMethodContext getDefault() {
public KNNMethodContext(StreamInput in) throws IOException {
this.knnEngine = KNNEngine.getEngine(in.readString());
this.spaceType = SpaceType.getSpace(in.readString());
this.methodComponent = new MethodComponentContext(in);
this.methodComponentContext = new MethodComponentContext(in);
}

/**
Expand Down Expand Up @@ -198,7 +198,7 @@ public static KNNMethodContext parse(Object in) {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.field(KNN_ENGINE, knnEngine.getName());
builder.field(METHOD_PARAMETER_SPACE_TYPE, spaceType.getValue());
builder = methodComponent.toXContent(builder, params);
builder = methodComponentContext.toXContent(builder, params);
return builder;
}

Expand All @@ -211,20 +211,20 @@ public boolean equals(Object obj) {
EqualsBuilder equalsBuilder = new EqualsBuilder();
equalsBuilder.append(knnEngine, other.knnEngine);
equalsBuilder.append(spaceType, other.spaceType);
equalsBuilder.append(methodComponent, other.methodComponent);
equalsBuilder.append(methodComponentContext, other.methodComponentContext);

return equalsBuilder.isEquals();
}

@Override
public int hashCode() {
return new HashCodeBuilder().append(knnEngine).append(spaceType).append(methodComponent).toHashCode();
return new HashCodeBuilder().append(knnEngine).append(spaceType).append(methodComponentContext).toHashCode();
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(knnEngine.getName());
out.writeString(spaceType.getValue());
this.methodComponent.writeTo(out);
this.methodComponentContext.writeTo(out);
}
}
16 changes: 10 additions & 6 deletions src/main/java/org/opensearch/knn/index/KNNSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.OpenSearchParseException;
import org.opensearch.cluster.metadata.IndexMetadata;
import org.opensearch.core.action.ActionListener;
import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
Expand All @@ -21,6 +22,7 @@
import org.opensearch.index.IndexModule;
import org.opensearch.knn.index.memory.NativeMemoryCacheManager;
import org.opensearch.knn.index.memory.NativeMemoryCacheManagerDto;
import org.opensearch.knn.index.util.IndexHyperParametersUtil;
import org.opensearch.monitor.jvm.JvmInfo;
import org.opensearch.monitor.os.OsProbe;

Expand Down Expand Up @@ -81,7 +83,8 @@ public class KNNSettings {
public static final String INDEX_KNN_DEFAULT_SPACE_TYPE = "l2";
public static final Integer INDEX_KNN_DEFAULT_ALGO_PARAM_M = 16;
public static final Integer INDEX_KNN_DEFAULT_ALGO_PARAM_EF_SEARCH = 512;
public static final Integer INDEX_KNN_DEFAULT_ALGO_PARAM_EF_CONSTRUCTION = 512;
public static final Integer INDEX_KNN_NEW_DEFAULT_ALGO_PARAM_EF_SEARCH = 100;
public static final Integer INDEX_KNN_DEFAULT_ALGO_PARAM_EF_CONSTRUCTION = 100;
public static final Integer KNN_DEFAULT_ALGO_PARAM_INDEX_THREAD_QTY = 1;
public static final Integer KNN_DEFAULT_CIRCUIT_BREAKER_UNSET_PERCENTAGE = 75;
public static final Integer KNN_DEFAULT_MODEL_CACHE_SIZE_LIMIT_PERCENTAGE = 10; // By default, set aside 10% of the JVM for the limit
Expand Down Expand Up @@ -447,11 +450,12 @@ public void onFailure(Exception e) {
* @return efSearch value
*/
public static int getEfSearchParam(String index) {
return KNNSettings.state().clusterService.state()
.getMetadata()
.index(index)
.getSettings()
.getAsInt(KNNSettings.KNN_ALGO_PARAM_EF_SEARCH, 512);
final IndexMetadata indexMetadata = KNNSettings.state().clusterService.state().getMetadata().index(index);
return indexMetadata.getSettings()
.getAsInt(
KNNSettings.KNN_ALGO_PARAM_EF_SEARCH,
IndexHyperParametersUtil.getHNSWEFSearchValue(indexMetadata.getCreationVersion())
);
}

public void setClusterService(ClusterService clusterService) {
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/org/opensearch/knn/index/MethodComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
package org.opensearch.knn.index;

import lombok.Getter;
import org.opensearch.Version;
import org.opensearch.common.TriFunction;
import org.opensearch.common.ValidationException;
import org.opensearch.knn.common.KNNConstants;
import org.opensearch.knn.index.util.IndexHyperParametersUtil;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -296,11 +298,24 @@ public static Map<String, Object> getParameterMapWithDefaultsAdded(
) {
Map<String, Object> parametersWithDefaultsMap = new HashMap<>();
Map<String, Object> userProvidedParametersMap = methodComponentContext.getParameters();
Version indexCreationVersion = methodComponentContext.getIndexVersion();
for (Parameter<?> parameter : methodComponent.getParameters().values()) {
if (methodComponentContext.getParameters().containsKey(parameter.getName())) {
parametersWithDefaultsMap.put(parameter.getName(), userProvidedParametersMap.get(parameter.getName()));
} else {
parametersWithDefaultsMap.put(parameter.getName(), parameter.getDefaultValue());
// Pick up new values here. Make sure that index settings is passed till here,
// Version.fromId(Integer.parseInt((String)context.indexSettings.settings.get("index.version.created")))
if (parameter.getName().equals(KNNConstants.METHOD_PARAMETER_EF_SEARCH)) {
parametersWithDefaultsMap.put(parameter.getName(), IndexHyperParametersUtil.getHNSWEFSearchValue(indexCreationVersion));
} else if (parameter.getName().equals(KNNConstants.METHOD_PARAMETER_EF_CONSTRUCTION)) {
parametersWithDefaultsMap.put(
parameter.getName(),
IndexHyperParametersUtil.getHNSWEFConstructionValue(indexCreationVersion)
);
} else {
parametersWithDefaultsMap.put(parameter.getName(), parameter.getDefaultValue());
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

package org.opensearch.knn.index;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.opensearch.Version;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
import org.opensearch.core.common.io.stream.Writeable;
Expand All @@ -36,13 +38,18 @@
*
* Each component is composed of a name and a map of parameters.
*/
@AllArgsConstructor
@RequiredArgsConstructor
public class MethodComponentContext implements ToXContentFragment, Writeable {

@Getter
private final String name;
private final Map<String, Object> parameters;

// Need a code over here to make sure that we are reading and writing in stream this optional index version.
@Getter
@Setter
private Version indexVersion;

/**
* Constructor from stream.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public KnnVectorsFormat getKnnVectorsFormatForField(final String field) {
String.format("Cannot read field type for field [%s] because mapper service is not available", field)
)
).fieldType(field);
var params = type.getKnnMethodContext().getMethodComponent().getParameters();
var params = type.getKnnMethodContext().getMethodComponentContext().getParameters();
int maxConnections = getMaxConnections(params);
int beamWidth = getBeamWidth(params);
log.debug(
Expand Down
Loading

0 comments on commit 3a0e1ec

Please sign in to comment.