Skip to content

Commit 9445c01

Browse files
committed
add comments
1 parent d2aa214 commit 9445c01

File tree

2 files changed

+55
-13
lines changed

2 files changed

+55
-13
lines changed

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,23 +223,43 @@ public int compareTo(AssignmentPlan o) {
223223
return Comparator.comparing(AssignmentPlan::computeQuality).compare(this, o);
224224
}
225225

226+
/**
227+
* Checks whether all deployments in the current {@link AssignmentPlan} have at least as many
228+
* allocations as currently assigned.
229+
*/
226230
public boolean satisfiesCurrentAssignments() {
227231
return deployments().stream().allMatch(this::isSatisfyingCurrentAssignmentsForModel);
228232
}
229233

234+
/**
235+
* Checks whether the current assignments for a given {@link Deployment} meet its allocation requirements.
236+
*
237+
* It ensures that the total number of allocations assigned to the deployment across all nodes is
238+
* at least equal to the deployment's current assigned allocations.
239+
*/
230240
private boolean isSatisfyingCurrentAssignmentsForModel(Deployment m) {
231241
if (m.currentAllocationsByNodeId().isEmpty()) {
232242
return true;
233243
}
234244
Map<Node, Integer> nodeAssignments = assignments.get(m);
235-
int currentAllocations = nodeAssignments.values().stream().mapToInt(Integer::intValue).sum();
236-
return currentAllocations >= m.getCurrentAssignedAllocations();
245+
int inPlanAssignedAllocations = nodeAssignments.values().stream().mapToInt(Integer::intValue).sum();
246+
return inPlanAssignedAllocations >= m.getCurrentAssignedAllocations();
237247
}
238248

239-
public boolean satisfiesAllocations(Deployment m) {
240-
return remainingModelAllocations.getOrDefault(m, 0) == 0;
249+
/**
250+
* Checks if the current assignments satisfy the deployment's allocation requirements.
251+
* @param deployment the deployment to check
252+
* @return true if the current assignments satisfy the deployments's allocation requirements, false otherwise
253+
*/
254+
public boolean satisfiesAllocations(Deployment deployment) {
255+
return remainingModelAllocations.getOrDefault(deployment, 0) == 0;
241256
}
242257

258+
/**
259+
* Checks if the current assignments satisfy all deployments' allocation requirements. This means that
260+
* each deployment has no remaining allocations left to assign.
261+
* @return true if the current assignments satisfy the deployments' allocation requirements, false otherwise
262+
*/
243263
public boolean satisfiesAllModels() {
244264
return deployments().stream().allMatch(this::satisfiesAllocations);
245265
}

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

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,26 @@ public AssignmentPlan computePlan() {
6060
return computePlan(true);
6161
}
6262

63-
public AssignmentPlan computePlan(boolean tryAssigningPreviouslyAssignedModels) {
63+
/**
64+
* Computes an {@link AssignmentPlan} for the given nodes and deployments.
65+
* If {@code tryAssigningAllPreviouslyAllocatedModels} is true, then the plan will
66+
* attempt to assign at least one allocation to previously assigned models.
67+
* Otherwise, it will only ensure that deployments assigned to existing nodes will preserve at least one allocation
68+
*
69+
* @param tryAssigningAllPreviouslyAllocatedModels whether to do the best effort assigning previously assigned models somewhere
70+
* with at least one allocation
71+
* @return the computed assignment plan
72+
*/
73+
public AssignmentPlan computePlan(boolean tryAssigningAllPreviouslyAllocatedModels) {
6474
logger.debug(() -> format("Computing plan for nodes = %s; deployments = %s", nodes, deployments));
6575

6676
AssignmentPlan bestPlan;
6777
AssignmentPlan planSatisfyingCurrentAssignments = solveSatisfyingCurrentAssignments();
6878
logger.debug(() -> "Plan satisfying current assignments =\n" + planSatisfyingCurrentAssignments.prettyPrint());
69-
if (planSatisfyingCurrentAssignments.arePreviouslyAssignedModelsAssigned() == false && tryAssigningPreviouslyAssignedModels) {
79+
if (planSatisfyingCurrentAssignments.arePreviouslyAssignedModelsAssigned() || tryAssigningAllPreviouslyAllocatedModels == false) {
80+
bestPlan = planSatisfyingCurrentAssignments;
81+
} else {
82+
// try to resue any deployment that would otherwise drop to zero allocations
7083
AssignmentPlan planAllocatingAtLeastOnceModelsThatWerePreviouslyAllocated =
7184
solveAllocatingAtLeastOnceModelsThatWerePreviouslyAllocated();
7285
logger.debug(
@@ -82,28 +95,37 @@ public AssignmentPlan computePlan(boolean tryAssigningPreviouslyAssignedModels)
8295
? planSatisfyingCurrentAssignments
8396
: planAllocatingAtLeastOnceModelsThatWerePreviouslyAllocated;
8497
}
85-
} else {
86-
bestPlan = planSatisfyingCurrentAssignments;
8798
}
8899

89100
logger.debug(() -> "Best plan =\n" + bestPlan.prettyPrint());
90101
logger.debug(() -> prettyPrintOverallStats(bestPlan));
91102
return bestPlan;
92103
}
93104

105+
/**
106+
* Computes the best assignment plan from two strategies:
107+
* 1. Preserving one allocation on current assignments, which is the most flexible
108+
* 2. Preserving all allocations on current assignments, which is more conservative
109+
* @return the best assignment plan
110+
*/
94111
private AssignmentPlan solveSatisfyingCurrentAssignments() {
95112
AssignmentPlan bestPlan;
96113
// First solve preserving one allocation per assignment because that is most flexible
97114
AssignmentPlan planKeepingOneAllocationOnCurrentAssignments = solveKeepingOneAllocationOnCurrentAssignments();
98-
if (planKeepingOneAllocationOnCurrentAssignments.satisfiesCurrentAssignments() == false) {
115+
116+
if (planKeepingOneAllocationOnCurrentAssignments.satisfiesAllModels()) {
117+
// If the plan satisfies all models, then we can use it as is
118+
bestPlan = planKeepingOneAllocationOnCurrentAssignments;
119+
} else if (planKeepingOneAllocationOnCurrentAssignments.satisfiesCurrentAssignments() == false) {
120+
// If in the new assignment plan, some deployments have fewer allocations than in the current assignments,
121+
// try explicitly preserving all allocations on current assignments.
99122
bestPlan = solvePreservingAllAllocationsOnCurrentAssignments();
100-
} else if (planKeepingOneAllocationOnCurrentAssignments.satisfiesAllModels() == false) {
123+
} else {
124+
// Choose the best strategy according to {@link AssignmentPlan#computeQuality(AssignmentPlan)}
101125
AssignmentPlan planKeepingAllAllocationsOnCurrentAssignments = solvePreservingAllAllocationsOnCurrentAssignments();
102126
bestPlan = planKeepingAllAllocationsOnCurrentAssignments.compareTo(planKeepingOneAllocationOnCurrentAssignments) >= 0
103127
? planKeepingAllAllocationsOnCurrentAssignments
104128
: planKeepingOneAllocationOnCurrentAssignments;
105-
} else {
106-
bestPlan = planKeepingOneAllocationOnCurrentAssignments;
107129
}
108130
return bestPlan;
109131
}
@@ -120,7 +142,7 @@ private AssignmentPlan solveAllocatingAtLeastOnceModelsThatWerePreviouslyAllocat
120142
1,
121143
m.threadsPerAllocation(),
122144
// don't rely on the current allocation
123-
new HashMap<>(),
145+
Map.of(),
124146
m.maxAssignedAllocations(),
125147
m.getAdaptiveAllocationsSettings(),
126148
m.perDeploymentMemoryBytes(),

0 commit comments

Comments
 (0)