Skip to content

Commit e28eaf0

Browse files
committed
Preserve deployments with zero allocations during assignment planning.
1 parent c9dcc3b commit e28eaf0

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/planning/AssignmentPlan.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.util.ArrayList;
1818
import java.util.Collection;
19+
import java.util.Collections;
1920
import java.util.Comparator;
2021
import java.util.HashMap;
2122
import java.util.HashSet;
@@ -190,15 +191,13 @@ public String toString() {
190191

191192
private AssignmentPlan(
192193
Map<Deployment, Map<Node, Integer>> assignments,
193-
Map<Node, Long> remainingNodeMemory,
194-
Map<Node, Integer> remainingNodeCores,
194+
Map<String, Long> remainingNodeMemory,
195+
Map<String, Integer> remainingNodeCores,
195196
Map<Deployment, Integer> remainingModelAllocations
196197
) {
197198
this.assignments = Objects.requireNonNull(assignments);
198-
this.remainingNodeMemory = remainingNodeMemory.entrySet()
199-
.stream()
200-
.collect(Collectors.toMap(e -> e.getKey().id(), e -> e.getValue()));
201-
this.remainingNodeCores = remainingNodeCores.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().id(), e -> e.getValue()));
199+
this.remainingNodeMemory = Objects.requireNonNull(remainingNodeMemory);
200+
this.remainingNodeCores = Objects.requireNonNull(remainingNodeCores);
202201
this.remainingModelAllocations = Objects.requireNonNull(remainingModelAllocations);
203202
}
204203

@@ -315,6 +314,14 @@ private Quality computeQuality() {
315314
return new Quality(isSatisfyingPreviousAssignments, weighedAllocationsScore, memoryScore);
316315
}
317316

317+
public AssignmentPlan withDeploymentsWithZeroAllocations(Collection<Deployment> deploymentsWithZeroAllocations) {
318+
Map<Deployment, Map<Node, Integer>> newAssignments = new HashMap<>(assignments);
319+
for (Deployment deployment : deploymentsWithZeroAllocations) {
320+
newAssignments.put(deployment, Collections.emptyMap());
321+
}
322+
return new AssignmentPlan(newAssignments, remainingNodeMemory, remainingNodeCores, remainingModelAllocations);
323+
}
324+
318325
public String prettyPrint() {
319326
if (assignments.isEmpty()) {
320327
return "Empty plan";
@@ -477,7 +484,12 @@ public AssignmentPlan build() {
477484
}
478485
finalAssignments.put(m, allocationsPerNode);
479486
}
480-
return new AssignmentPlan(finalAssignments, remainingNodeMemory, remainingNodeCores, remainingModelAllocations);
487+
return new AssignmentPlan(
488+
finalAssignments,
489+
remainingNodeMemory.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().id(), Map.Entry::getValue)),
490+
remainingNodeCores.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().id(), Map.Entry::getValue)),
491+
remainingModelAllocations
492+
);
481493
}
482494
}
483495

x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/planning/AssignmentPlanner.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,18 @@ public class AssignmentPlanner {
4747

4848
private final List<Node> nodes;
4949
private final List<AssignmentPlan.Deployment> deployments;
50+
private final List<AssignmentPlan.Deployment> deploymentsWithZeroAllocations;
5051

5152
public AssignmentPlanner(List<Node> nodes, List<AssignmentPlan.Deployment> deployments) {
5253
this.nodes = nodes.stream().sorted(Comparator.comparing(Node::id)).toList();
5354
this.deployments = deployments.stream()
5455
.filter(deployment -> deployment.allocations() > 0)
5556
.sorted(Comparator.comparing(AssignmentPlan.Deployment::deploymentId))
5657
.toList();
58+
this.deploymentsWithZeroAllocations = deployments.stream()
59+
.filter(deployment -> deployment.allocations() == 0)
60+
.sorted(Comparator.comparing(AssignmentPlan.Deployment::deploymentId))
61+
.toList();
5762
}
5863

5964
public AssignmentPlan computePlan() {
@@ -99,7 +104,8 @@ public AssignmentPlan computePlan(boolean tryAssigningAllPreviouslyAllocatedMode
99104

100105
logger.debug(() -> "Best plan =\n" + bestPlan.prettyPrint());
101106
logger.debug(() -> prettyPrintOverallStats(bestPlan));
102-
return bestPlan;
107+
108+
return bestPlan.withDeploymentsWithZeroAllocations(deploymentsWithZeroAllocations);
103109
}
104110

105111
/**

x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/inference/assignment/planning/AssignmentPlannerTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.common.StopWatch;
1111
import org.elasticsearch.common.unit.ByteSizeValue;
1212
import org.elasticsearch.test.ESTestCase;
13+
import org.elasticsearch.xpack.core.ml.inference.assignment.AdaptiveAllocationsSettings;
1314
import org.elasticsearch.xpack.ml.inference.assignment.planning.AssignmentPlan.Deployment;
1415
import org.elasticsearch.xpack.ml.inference.assignment.planning.AssignmentPlan.Node;
1516

@@ -24,6 +25,7 @@
2425
import java.util.stream.Stream;
2526

2627
import static org.elasticsearch.test.hamcrest.OptionalMatchers.isEmpty;
28+
import static org.hamcrest.Matchers.contains;
2729
import static org.hamcrest.Matchers.equalTo;
2830
import static org.hamcrest.Matchers.everyItem;
2931
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
@@ -1165,7 +1167,28 @@ public void testGivenClusterResize_ShouldRemoveAllocatedDeployments_NewMemoryFie
11651167
assertThat(indexedBasedPlan.get("m_1"), equalTo(Map.of("n_1", 2)));
11661168
assertThat(assignmentPlan.getRemainingNodeMemory(node1.id()), greaterThanOrEqualTo(0L));
11671169
assertThat(assignmentPlan.getRemainingNodeCores(node1.id()), greaterThanOrEqualTo(0));
1170+
}
1171+
1172+
public void testDeploymentWithZeroAllocationsIsPreserved() {
1173+
Node node = new Node("n_1", ByteSizeValue.ofGb(4).getBytes(), 4);
1174+
Deployment deployment = new Deployment(
1175+
"m_1",
1176+
"m_1",
1177+
ByteSizeValue.ofMb(500).getBytes(),
1178+
0,
1179+
1,
1180+
Map.of(),
1181+
0,
1182+
new AdaptiveAllocationsSettings(true, 0, 42),
1183+
0,
1184+
0
1185+
);
1186+
1187+
AssignmentPlan assignmentPlan = new AssignmentPlanner(List.of(node), List.of(deployment)).computePlan();
11681188

1189+
assertThat(assignmentPlan.deployments(), contains(deployment));
1190+
assertThat(assignmentPlan.getRemainingNodeMemory(node.id()), equalTo(ByteSizeValue.ofGb(4).getBytes()));
1191+
assertThat(assignmentPlan.getRemainingNodeCores(node.id()), equalTo(4));
11691192
}
11701193

11711194
public static List<Deployment> createDeploymentsFromPlan(AssignmentPlan plan) {

0 commit comments

Comments
 (0)