-
Notifications
You must be signed in to change notification settings - Fork 251
feat(scheduler): add gpujoborder plugin for configurable JobOrderFn tiebreak #1995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
davidLif
merged 14 commits into
kai-scheduler:main
from
CoolingCube:resourceaware-tiebreak
Aug 23, 2026
Merged
Changes from 7 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
e3144dd
Add resourceaware plugin: configurable resource-based JobOrderFn tieb…
CoolingCube 60f765c
Register resourceaware plugin in factory.go; restore priority guard c…
CoolingCube c5ff98c
chore: add changelog fragment for resourceaware plugin
CoolingCube 279043f
refactor(scheduler): rename resourceaware plugin to gpujoborder for c…
CoolingCube d366fa3
docs: update changelog fragment to reference gpujoborder
CoolingCube ff245ea
perf(scheduler): cache GetAliveTasksRequestedGPUs to fix reclaim benc…
CoolingCube 8a53739
chore: add license headers and fix formatting to pass make validate
CoolingCube c7b3e9e
fix(scheduler): scope gpujoborder to victim selection only via new Vi…
CoolingCube 5991c05
fix(scheduler): VictimOrderFn correctly composes with existing JobOrd…
CoolingCube 04467da
test(scheduler): fix duplicate task UIDs in elastic-composition test …
CoolingCube 2b6eade
style(scheduler): remove comments per @gshaibi's review preference
CoolingCube 24d2587
style(scheduler): remove comment from new test, matching bare-minimum…
CoolingCube 99cd1c2
docs(scheduler): add doc comments for the VictimOrderFn extension point
CoolingCube 587dab3
Merge branch 'main' into resourceaware-tiebreak
CoolingCube File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| kind: Added | ||
| body: |- | ||
| Add gpujoborder plugin for configurable GPU-based JobOrderFn tiebreak on priority ties |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // Copyright 2026 NVIDIA CORPORATION | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package gpujoborder | ||
|
|
||
| import ( | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/podgroup_info" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/framework" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/log" | ||
| ) | ||
|
|
||
| const ( | ||
| ModePreferLarger = "prefer-larger" | ||
|
CoolingCube marked this conversation as resolved.
Outdated
|
||
| ModePreferSmaller = "prefer-smaller" | ||
| ) | ||
|
|
||
| type gpuJobOrderPlugin struct { | ||
| mode string | ||
| } | ||
|
|
||
| func New(arguments framework.PluginArguments) framework.Plugin { | ||
| mode := arguments.GetString("mode", ModePreferLarger) | ||
| if mode != ModePreferLarger && mode != ModePreferSmaller { | ||
| log.InfraLogger.Warningf("gpujoborder: unrecognized mode %q, defaulting to prefer-larger", mode) | ||
| mode = ModePreferLarger | ||
| } | ||
| return &gpuJobOrderPlugin{mode: mode} | ||
| } | ||
|
|
||
| func (rp *gpuJobOrderPlugin) Name() string { | ||
| return "gpujoborder" | ||
| } | ||
|
|
||
| func (rp *gpuJobOrderPlugin) OnSessionOpen(ssn *framework.Session) { | ||
| ssn.AddJobOrderFn(rp.JobOrderFn) | ||
| } | ||
|
|
||
| func (rp *gpuJobOrderPlugin) JobOrderFn(l, r interface{}) int { | ||
| lv := l.(*podgroup_info.PodGroupInfo) | ||
| rv := r.(*podgroup_info.PodGroupInfo) | ||
|
|
||
| if lv.Priority != rv.Priority { | ||
| return 0 | ||
| } | ||
|
|
||
| lGPU := lv.GetAliveTasksRequestedGPUs() | ||
| rGPU := rv.GetAliveTasksRequestedGPUs() | ||
|
|
||
| switch rp.mode { | ||
| case ModePreferSmaller: | ||
| if lGPU < rGPU { | ||
| return -1 | ||
| } | ||
| if lGPU > rGPU { | ||
| return 1 | ||
| } | ||
| default: // ModePreferLarger | ||
| if lGPU > rGPU { | ||
| return -1 | ||
| } | ||
| if lGPU < rGPU { | ||
| return 1 | ||
| } | ||
| } | ||
| return 0 | ||
| } | ||
|
|
||
| func (rp *gpuJobOrderPlugin) OnSessionClose(_ *framework.Session) {} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| // Copyright 2026 NVIDIA CORPORATION | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package gpujoborder | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/common_info" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/pod_info" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/pod_status" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/podgroup_info" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/api/resource_info" | ||
| "github.com/kai-scheduler/KAI-scheduler/pkg/scheduler/framework" | ||
| ) | ||
|
|
||
| func makeGPUPodGroup(uid string, priority int32, gpuCount float64, vm *resource_info.ResourceVectorMap) *podgroup_info.PodGroupInfo { | ||
| task := &pod_info.PodInfo{ | ||
| UID: common_info.PodID(uid + "-task"), | ||
| ResReqVector: resource_info.NewResourceVectorWithValues(0, 0, gpuCount, vm), | ||
| Status: pod_status.Running, | ||
| } | ||
| pg := podgroup_info.NewPodGroupInfoWithVectorMap(common_info.PodGroupID(uid), vm, task) | ||
| pg.Priority = priority | ||
| return pg | ||
| } | ||
|
|
||
| func newPlugin(t *testing.T, mode string) *gpuJobOrderPlugin { | ||
| t.Helper() | ||
| args := framework.PluginArguments{} | ||
| if mode != "" { | ||
| args["mode"] = mode | ||
| } | ||
| rp, ok := New(args).(*gpuJobOrderPlugin) | ||
| if !ok { | ||
| t.Fatalf("New() did not return *gpuJobOrderPlugin") | ||
| } | ||
| return rp | ||
| } | ||
|
|
||
| func TestJobOrderFn_PriorityDiffers_Defers(t *testing.T) { | ||
| vm := resource_info.NewResourceVectorMap() | ||
| a := makeGPUPodGroup("a", 50, 1, vm) | ||
| b := makeGPUPodGroup("b", 10, 1, vm) | ||
| rp := newPlugin(t, "") | ||
| if got := rp.JobOrderFn(a, b); got != 0 { | ||
| t.Errorf("expected 0 when priorities differ, got %d", got) | ||
| } | ||
| } | ||
|
|
||
| func TestJobOrderFn_SamePriority_PrefersLarger_Default(t *testing.T) { | ||
| vm := resource_info.NewResourceVectorMap() | ||
| small := makeGPUPodGroup("small", 10, 1, vm) | ||
| large := makeGPUPodGroup("large", 10, 2, vm) | ||
| rp := newPlugin(t, "") | ||
| if got := rp.JobOrderFn(large, small); got != -1 { | ||
| t.Errorf("expected -1 (larger job preferred as victim), got %d", got) | ||
| } | ||
| if got := rp.JobOrderFn(small, large); got != 1 { | ||
| t.Errorf("expected 1, got %d", got) | ||
| } | ||
| } | ||
|
|
||
| func TestJobOrderFn_SamePriority_SameGPU_FallsThrough(t *testing.T) { | ||
| vm := resource_info.NewResourceVectorMap() | ||
| a := makeGPUPodGroup("a", 10, 1, vm) | ||
| b := makeGPUPodGroup("b", 10, 1, vm) | ||
| rp := newPlugin(t, "") | ||
| if got := rp.JobOrderFn(a, b); got != 0 { | ||
| t.Errorf("expected 0 (equal GPU falls through), got %d", got) | ||
| } | ||
| } | ||
|
|
||
| func TestJobOrderFn_PreferSmallerMode(t *testing.T) { | ||
| vm := resource_info.NewResourceVectorMap() | ||
| small := makeGPUPodGroup("small", 10, 1, vm) | ||
| large := makeGPUPodGroup("large", 10, 2, vm) | ||
| rp := newPlugin(t, "prefer-smaller") | ||
| if got := rp.JobOrderFn(small, large); got != -1 { | ||
| t.Errorf("expected -1 (smaller job preferred as victim in prefer-smaller mode), got %d", got) | ||
| } | ||
| if got := rp.JobOrderFn(large, small); got != 1 { | ||
| t.Errorf("expected 1, got %d", got) | ||
| } | ||
| } | ||
|
|
||
| func TestNew_UnrecognizedMode_FallsBackToPreferLarger(t *testing.T) { | ||
| vm := resource_info.NewResourceVectorMap() | ||
| small := makeGPUPodGroup("small", 10, 1, vm) | ||
| large := makeGPUPodGroup("large", 10, 2, vm) | ||
| rp := newPlugin(t, "totally-not-a-real-mode") | ||
| if got := rp.JobOrderFn(large, small); got != -1 { | ||
| t.Errorf("expected fallback to prefer-larger behavior, got %d", got) | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.