Skip to content

docs: propose composable scheduler policy chain - #2077

Closed
AnkushUjawane wants to merge 2 commits into
Project-HAMi:masterfrom
AnkushUjawane:docs/scheduler-policy-composition
Closed

docs: propose composable scheduler policy chain#2077
AnkushUjawane wants to merge 2 commits into
Project-HAMi:masterfrom
AnkushUjawane:docs/scheduler-policy-composition

Conversation

@AnkushUjawane

@AnkushUjawane AnkushUjawane commented Jul 16, 2026

Copy link
Copy Markdown

What type of PR is this?
/kind design

What this PR does / why we need it:
This PR proposes a design for two v2.10 roadmap items: a composable scheduler
policy chain (node-scheduler-policy / gpu-scheduler-policy currently only
support a single policy at a time, e.g. "binpack" OR "spread" OR
"topology-aware", with no way to combine dimensions like NUMA + binpack), and
a new mutex scheduling policy for hard mutual-exclusion constraints between
pods/devices.

The composable chain also addresses the root cause of #1806: gpu_policy.go's
Less() already hardcodes a two-dimension comparison (NUMA, then Score) but
it isn't configurable or extensible to other dimensions.

This is a design doc only — no code changes in this PR. I'd like feedback on
the approach before implementing.

Which issue(s) this PR fixes:
Relates to #1889, #1806

Special notes for your reviewer:

  • I used AI assistance to research the existing scheduler policy code
    (pkg/scheduler/policy/, pkg/scheduler/score.go, pkg/util/types.go)
    and draft an initial version of this doc, which I then reviewed and edited
    myself. Happy to discuss/defend any part of the design.
  • Two open questions I'd especially like input on: whether node-level combination
    needs a parallel NodeDimension interface alongside PolicyDimension, and
    whether hami.io/mutex-group is the right annotation name given existing
    nvidia.com/priority semantics (see FAQ HAMi FAQ #646).
  • Once this direction is agreed, I'd follow up with the actual code PR(s) —
    planning to split the policy-chain refactor and the mutex filter into
    separate PRs since they're independent.

Does this PR introduce a user-facing change?:

No user-facing change yet — this is a design proposal only. If accepted, the
follow-up implementation PR(s) will introduce:
- `hami.io/node-scheduler-policy` and `hami.io/gpu-scheduler-policy` will
  accept a comma-separated ordered list of policies (e.g. "numa,binpack") in
  addition to the existing single-value format, which remains fully
  backward compatible.
- A new `hami.io/mutex-group` (and `hami.io/mutex-scope`) Pod annotation for
  hard mutual-exclusion scheduling constraints.

Summary by CodeRabbit

  • Documentation
    • Added a specification for composable, lexicographically-evaluated scheduler policy chains with separate dimension handling for device ordering vs node ordering, including direction-aware NUMA dimensions and special handling for topology-aware.
    • Defined backward-compatible parsing for legacy single-value inputs, with warnings for unknown dimensions and guarantees to keep the chain stable and non-empty.
    • Introduced a new hard mutual-exclusion (“exclusion/mutex”) policy concept with updated annotation names, explicit empty-group behavior, device-scope vs node-scope enforcement, and a race-safe implementation approach.
    • Included examples, design considerations, and open questions.

@hami-robot

hami-robot Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: AnkushUjawane
Once this PR has been reviewed and has the lgtm label, please assign archlitchi for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions github-actions Bot added the kind/documentation Improvements or additions to documentation label Jul 16, 2026
@hami-robot

hami-robot Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Welcome @AnkushUjawane! It looks like this is your first PR to Project-HAMi/HAMi 🎉

@hami-robot hami-robot Bot added the size/L label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a documentation proposal for composable device and node scheduler policy chains and scheduler-level exclusion filtering, including compatibility rules, execution points, locking requirements, user stories, open questions, and implementation references.

Changes

Scheduler policy proposal

Layer / File(s) Summary
Composable policy chain
docs/develop/scheduler-policy-composition.md
Defines separate device and node comparator chains, lexicographic evaluation, NUMA direction handling, legacy parsing, topology-aware routing, fallback behavior, examples, open questions, and implementation references.
Exclusion filter
docs/develop/scheduler-policy-composition.md
Defines renamed exclusion annotations, device- and node-scope filtering points, empty-group behavior, pod scope sourcing, and per-node locking to avoid TOCTOU races.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related issues

  • Issue 2009 — Relates to the proposed scheduler-level exclusion/mutex behavior.
  • Issue 2010 — Relates to the documented composable policy chains and GPU/device ordering.

Suggested reviewers: wawa0210, chaunceyjiang

Poem

A bunny chains policies in a row,
While mutex carrots block the flow.
Devices hop, and nodes agree,
Locks keep the burrow race-free.
New scheduler specs now grow—
Hoppy design from ear to toe!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the proposed composable scheduler policy chain, which is a major change in the documentation, but it omits the mutex policy proposal.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request proposes a design document for a composable scheduler policy chain and a mutual-exclusion (mutex) policy in HAMi. The review feedback highlights several critical design and implementation concerns: the proposed NUMA sorting behavior breaks backward compatibility with the default spread policy; an empty policy chain could result in unstable sorting, which can be mitigated with a fallback mechanism; the mechanism for retrieving pod annotations for mutex-group checks needs clarification to avoid performance issues; and node-level mutex filtering should be optimized by executing it earlier in the scheduling loop.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md
Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
docs/develop/scheduler-policy-composition.md (1)

88-91: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make invalid-chain fallback semantics explicit.

The proposal does not state whether an unknown token discards the entire chain or is ignored. The fallback also differs by layer: the supplied GPU comparator defaults to spread behavior, while the node comparator defaults to binpack. Define per-layer parsing and fallback behavior, or reject invalid annotations instead of silently changing placement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/develop/scheduler-policy-composition.md` around lines 88 - 91, Clarify
the scheduler-policy composition proposal’s parsing semantics for unknown
tokens: define whether each invalid token is ignored or causes the entire chain
to fall back, separately for GPU and node layers. Explicitly document each
layer’s fallback comparator and behavior, including GPU spread and node binpack,
or specify that invalid annotations are rejected rather than silently changing
placement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/scheduler-policy-composition.md`:
- Around line 43-50: Update the NUMA dimension design around
numaDimension.Compare to preserve each policy’s legacy ordering: binpack must
use descending NUMA with ascending score, while the default spread path must use
ascending NUMA with descending score. Add explicit direction-aware dimension
implementations or configuration, and add legacy-mode tests covering both
policies before claiming backward compatibility.
- Around line 67-91: Document how every policy entry point constructs and
propagates the ordered dimension chain: update scheduler.go’s
GetGPUSchedulerPolicyByPod path and score.go’s configuration/annotation path to
invoke the parser, preserve the legacy Policy field for backward compatibility,
and copy the resulting Chain into DeviceUsageList and NodeScoreList. Specify
bare-value parsing, unknown-dimension fallback with warning logging, and ensure
Chain is populated before Less() comparisons.
- Around line 107-114: Add an atomic reservation or bind-time revalidation to
the mutex-group handling proposed around fitInDevices and
pkg/scheduler/score.go, so concurrent scheduling attempts cannot both pass the
conflict check and bind conflicting pods. Define and implement the required
scheduler serialization or assumed-state mechanism while preserving the
configured device/node mutex-scope behavior and hard no-co-location guarantee.
- Around line 97-114: The proposed mutex mechanism lacks the scheduling context
needed by CustomFilterRule to evaluate pod annotations and node occupancy.
Revise the design around fitInDevices to perform the mutex filter in scheduler
code with explicit access to the scheduling pod, candidate device/node, and all
pods bound to that node, or extend CustomFilterRule’s interface to provide
equivalent context. Ensure both device- and node-scoped exclusions can reliably
compare mutex-group and mutex-scope annotations.
- Around line 67-68: Define the node-level comparator contract before describing
or implementing a symmetric NodeScoreList chain: introduce a NodeDimension
abstraction compatible with *NodeScore, or establish a shared score abstraction
that both PolicyDimension and node comparisons can consume. Reuse shared parsing
and registration where appropriate, and update the NodeScoreList Less() design
to use the chosen contract instead of passing *NodeScore to
PolicyDimension.Compare.

---

Nitpick comments:
In `@docs/develop/scheduler-policy-composition.md`:
- Around line 88-91: Clarify the scheduler-policy composition proposal’s parsing
semantics for unknown tokens: define whether each invalid token is ignored or
causes the entire chain to fall back, separately for GPU and node layers.
Explicitly document each layer’s fallback comparator and behavior, including GPU
spread and node binpack, or specify that invalid annotations are rejected rather
than silently changing placement.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e95fdba-d8ca-49c0-bf1b-13eaa57655c5

📥 Commits

Reviewing files that changed from the base of the PR and between 03be4d8 and 624a29f.

📒 Files selected for processing (1)
  • docs/develop/scheduler-policy-composition.md

Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment on lines +67 to +91
`DeviceUsageList` (and analogously `NodeScoreList`) gains a `Chain
[]PolicyDimension` field, and `Less()` becomes:

```go
func (l DeviceUsageList) Less(i, j int) bool {
for _, dim := range l.Chain {
if c := dim.Compare(l.DeviceLists[i], l.DeviceLists[j]); c != 0 {
return c < 0
}
}
return false
}
```

**Config/annotation format** changes from a single value to a
comma-separated ordered list:

```yaml
hami.io/gpu-scheduler-policy: "numa,binpack"
```

Parsing is backward compatible: a bare `"binpack"` still parses to a
one-element chain, so existing clusters and Helm defaults keep working
unmodified. Unknown dimension names fall back to the default single-dimension
behavior with a warning log, rather than a hard error.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Specify chain construction and propagation at every policy entry point.

pkg/scheduler/scheduler.go currently populates DeviceUsageList.Policy from GetGPUSchedulerPolicyByPod, while pkg/scheduler/score.go populates NodeScoreList.Policy from configuration or pod annotations. If only Less() changes, Chain remains empty and its loop returns false for every comparison, effectively disabling policy ordering. Document parser invocation, legacy-field handling, and chain copying for these paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/develop/scheduler-policy-composition.md` around lines 67 - 91, Document
how every policy entry point constructs and propagates the ordered dimension
chain: update scheduler.go’s GetGPUSchedulerPolicyByPod path and score.go’s
configuration/annotation path to invoke the parser, preserve the legacy Policy
field for backward compatibility, and copy the resulting Chain into
DeviceUsageList and NodeScoreList. Specify bare-value parsing, unknown-dimension
fallback with warning logging, and ensure Chain is populated before Less()
comparisons.

Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated
@AnkushUjawane
AnkushUjawane force-pushed the docs/scheduler-policy-composition branch from d178531 to 08a71d6 Compare July 16, 2026 10:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/scheduler-policy-composition.md`:
- Around line 88-91: Update the comma-separated policy parser to recognize
“topology-aware” as the existing GPU policy and route it through the dedicated
NVIDIA handling unchanged, rather than treating it as an unknown dimension or
defaulting. Add a compatibility test covering the hami.io/gpu-scheduler-policy
annotation set to “topology-aware” and verify the legacy placement behavior is
preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a75b152-391c-4a27-b62f-6d3bcd2f8164

📥 Commits

Reviewing files that changed from the base of the PR and between d178531 and 08a71d6.

📒 Files selected for processing (1)
  • docs/develop/scheduler-policy-composition.md

Comment thread docs/develop/scheduler-policy-composition.md Outdated
@AnkushUjawane
AnkushUjawane force-pushed the docs/scheduler-policy-composition branch from 08a71d6 to 8826cb6 Compare July 16, 2026 11:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/scheduler-policy-composition.md`:
- Around line 120-125: Update the parser invariant description to distinguish
recognized legacy policies from empty or invalid input: map `binpack` to
`[numa-desc, binpack]` and `spread` to `[numa-asc, spread]`, while retaining
`[numa-asc, spread]` only as the fallback for empty or unparseable values.
- Around line 197-205: Update the scheduler policy composition proposal to
explicitly define that a missing or empty hami.io/exclusion-group disables
exclusion and never matches another empty value. Also specify the source and
matching contract for hami.io/exclusion-scope—whether it is taken from the
scheduling pod, incumbent pod, or required on both sides—so scope evaluation is
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a610187-ef6f-4c0d-8034-d57b9d47daf8

📥 Commits

Reviewing files that changed from the base of the PR and between 08a71d6 and 8826cb6.

📒 Files selected for processing (1)
  • docs/develop/scheduler-policy-composition.md

Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated
@AnkushUjawane
AnkushUjawane force-pushed the docs/scheduler-policy-composition branch from 8826cb6 to 912240b Compare July 16, 2026 11:18

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/scheduler-policy-composition.md`:
- Around line 262-263: Update the scheduler policy documentation sentence to
hyphenate “bin-packed” in the description of GPU placement, while preserving the
rest of the wording unchanged.
- Around line 221-227: Update the scope-source rule in the scheduler policy
documentation so exclusion scope is symmetric between the scheduling pod and
incumbent same-group pods, using the broader scope when they differ. Revise the
corresponding explanation and the section around the follow-up guarantee so the
documented behavior preserves the hard no-co-location guarantee across node and
device scopes.
- Around line 163-179: Update ParseDeviceChain to return a tagged result or
preserve the original policy string alongside []DeviceDimension, allowing the
caller to distinguish the explicit "topology-aware" policy from unknown
dimensions. Route that signal through the existing NVIDIA device-combination
path unchanged, while retaining warning-and-default-chain behavior for other
unknown tokens and adding the required compatibility test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 49b32ad4-0431-47db-97ff-e0f3542ed8d6

📥 Commits

Reviewing files that changed from the base of the PR and between 8826cb6 and 912240b.

📒 Files selected for processing (1)
  • docs/develop/scheduler-policy-composition.md

Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated
Comment thread docs/develop/scheduler-policy-composition.md Outdated
Signed-off-by: AnkushUjawane <multiverse1808@gmail.com>
@AnkushUjawane
AnkushUjawane force-pushed the docs/scheduler-policy-composition branch from 912240b to 2fd49fe Compare July 16, 2026 11:29
@mesutoezdil

mesutoezdil commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

both roadmap items here (mutex policy, policy combination) are already assigned in #1889, and pr 2011 already ships a mutex gpu-scheduler-policy value and pr 2012 already has a pending fix for #1806

might be worth coordinating on #1889 first like other contributors did before designing further with @archlitchi

@mesutoezdil

Copy link
Copy Markdown
Contributor

/hold

@mesutoezdil

Copy link
Copy Markdown
Contributor

Mutex + #1806 fix already merged via #2011, those sections are obsolete.
Still relevant: composable chain (#1889).
Please narrow the doc to that and rebase, or we close and track in #1889.

@mesutoezdil

Copy link
Copy Markdown
Contributor

/unhold

…HAMi#1806 sections (superseded by Project-HAMi#2011)

Signed-off-by: AnkushUjawane <multiverse1808@gmail.com>
@AnkushUjawane

Copy link
Copy Markdown
Author

Rebased and narrowed to just the composable chain — dropped the mutex and #1806-sort sections entirely since #2011 covers both. This revision proposes zero behavior change: verified the chain construction reproduces #2011's current four resolved paths (mutex, numa-bind×binpack, numa-bind×spread, default) exactly, via an equivalence table in the doc. Also flagged #2220 as a concrete example of the kind of addition this would make easier going forward, since it'd otherwise be a fourth hand-edited branch in Less().

@mesutoezdil

Copy link
Copy Markdown
Contributor

Rebased and narrowed to just the composable chain — dropped the mutex and #1806-sort sections entirely since #2011 covers both. This revision proposes zero behavior change: verified the chain construction reproduces #2011's current four resolved paths (mutex, numa-bind×binpack, numa-bind×spread, default) exactly, via an equivalence table in the doc. Also flagged #2220 as a concrete example of the kind of addition this would make easier going forward, since it'd otherwise be a fourth hand-edited branch in Less().

Reminder: Answers must be written by human being. You can view the relevant rule here.
https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
"4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed."

@mesutoezdil

Copy link
Copy Markdown
Contributor

title still says composable chain + mutex policy. body says mutex part got dropped. pls update title to match, just composable chain now.

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 62.93% <ø> (+2.77%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 27 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@AnkushUjawane AnkushUjawane changed the title docs: propose composable scheduler policy chain + mutex policy docs: propose composable scheduler policy chain Aug 11, 2026
@AnkushUjawane

Copy link
Copy Markdown
Author

Done, I change title name

@mesutoezdil

mesutoezdil commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

#2621 merged today
needs a rewrite against current master or should close

@AnkushUjawane
AnkushUjawane deleted the docs/scheduler-policy-composition branch August 13, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes kind/design kind/documentation Improvements or additions to documentation size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants