Skip to content

fix(nvidia): collapse duplicate MIG candidates in topology scheduling - #2751

Merged
hami-robot[bot] merged 1 commit into
Project-HAMi:masterfrom
Eshiv-Pandey:fix/topology-mig-candidate-pool
Aug 25, 2026
Merged

fix(nvidia): collapse duplicate MIG candidates in topology scheduling#2751
hami-robot[bot] merged 1 commit into
Project-HAMi:masterfrom
Eshiv-Pandey:fix/topology-mig-candidate-pool

Conversation

@Eshiv-Pandey

@Eshiv-Pandey Eshiv-Pandey commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?
/kind bug

What this PR does / why we need it:

NvidiaGPUDevices.Fit() re-examines a MIG card once per free MIG placement (if dev.Mode == "mig" { i++ }). In topology mode nothing short-circuits the collection loop, so each pass appends another candidate entry. An 8-card node with 7 free slices each produces 56 candidate entries describing only 8 physical cards — seven identical structs per card.

That inflated pool causes two defects:

  1. All devices land on one card. generateCombinations walks the slice in order, so the first combination emitted is N copies of the same card. computeBestCombination replaces the best only on totalScore > bestScore, so when no pair scores are published (every score 0) that first same-card combination wins the tie. A card has no pair score against itself, so a same-card set can never lose on score either. A 5-GPU request on an 8-card node is satisfied by 5 slices of one card, leaving 7 cards idle.

  2. Combinatorial blow-up. C(56,5) = 3,819,816 combinations are enumerate instead of C(8,5) = 56, per node, on the scheduling hot path.

Measured on 8 MIG cards x 7 free slices with the topology policy and no published pair scores: 2 GPUs -> 1 card in 1.15ms, 3 -> 1 card in 14.3ms, 4 -> 1 card in 237.7ms, 5 -> 1 card in 11.19s. The same 4-GPU request without the topology policy takes 53.8us and correctly picks 4 cards.

This PR collapses the candidate pool by physical card UUID before scoring, but only when the node has at least as many distinct cards as the pod requested. The duplicate entries are identical structs and pair scores are per physical
card, so they carry no information the scorer can use - dropping them cannot change which set of cards is best. The concrete MIG placement is still chosen later by selectMigCandidate() in AddResourceUsage(), so nothing is lost.

The len(distinct) >= originReq guard preserves packing multiple MIG instances onto one card when the node has no alternative - behaviour PR #2724 shows with hardware evidence is wanted.

After the fix all requests select the expected number of distinct cards, and the 5-GPU case drops from 11.19s to under 1ms.

Non-MIG nodes are unaffected: without MIG there are no duplicates, so the helper returns the slice unchanged and every path is byte-identical. The `== originReq exact-match branch is deliberately untouched - that pool is the only option, so
there is nothing to choose between.

Which issue(s) this PR fixes:
Fixes #2750

Special notes for your reviewer:

  • Existing topology tests are all non-MIG, so this interaction was untested; six tests added.
  • Verified both spread tests fail without the fix: the 2-GPU case picks 1 card (0.03s) and the 5-GPU case picks 1 card (~12s); both pass in 0.00s with it.
  • Known residual, out of scope: a request exceeding the node's card count keeps the full pool. pkg/scheduler/score.go rejects the node before Fit() runs, so it is unreachable unless fix(scheduler): allow multiple MIG instances on one GPU #2724 changes that gate.
  • Unrelated latent bug, untouched: computeWorstSingleCard dereferences deviceScoreMap[dev1.UUID].Scores with no nil check. Happy to file separately.
  • AI assistance disclosure: I used Claude Code for code analysis, the implementation, and the tests; all changes reviewed and verified by me.

Does this PR introduce a user-facing change?:

Fixed a bug where MIG devices were repeatedly allocated from a single physical GPU under the `topology` scheduler policy, leaving other free cards idle and causing exponential scheduling latency as the requested device count grew.

Topology scheduling collects every fitting candidate before choosing an
allocation, and Fit re-examines a MIG card once per free instance slot.
A card therefore contributes one interchangeable candidate per slot, so
an eight-card node with seven free slots each builds a 56-entry pool for
a request that only distinct physical cards should satisfy.

Pair scores are defined between physical cards and a card has no score
against itself, so the extra entries can never improve a combination.
They do two kinds of damage. On a node that publishes no pair scores
every combination ties at zero, so the first one generated wins, and
that is several slots of the same GPU while the other cards sit idle. On
any node the pool inflates the search: generateCombinations enumerates
C(56,5) rather than C(8,5), which took ~28s in a unit test.

Score one candidate per physical card whenever the node has at least as
many distinct cards as the request. Keep the full pool otherwise, so
several MIG instances on one card can still satisfy a request that no
set of distinct cards could.

Signed-off-by: Eshiv Pandey <eshivpandey18@gmail.com>
@hami-robot hami-robot Bot added the kind/bug Something isn't working label Aug 20, 2026
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e5ee3a8-112f-4005-8c8b-a9191b472c96

📥 Commits

Reviewing files that changed from the base of the PR and between ee92fc9 and afdec6f.

📒 Files selected for processing (2)
  • pkg/device/nvidia/device.go
  • pkg/device/nvidia/device_test.go

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

NVIDIA topology scheduling now deduplicates MIG candidates by physical GPU UUID when enough distinct cards are available. New tests cover spreading, score selection, single-card ranking, fallback packing, and candidate ordering.

Changes

MIG topology selection

Layer / File(s) Summary
Deduplicate topology candidates
pkg/device/nvidia/device.go
Topology selection uses UUID-deduplicated candidates when enough physical cards exist. It preserves the original candidates for fallback selection when fewer cards are available.
Validate MIG selection behavior
pkg/device/nvidia/device_test.go
Regression tests cover topology spreading, larger requests, scored pair selection, single-card ranking, fallback packing, and first-seen candidate ordering.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to afdec

This change prevents duplicate MIG candidates from concentrating allocations on one physical GPU and removes the associated scheduling slowdown; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

Suggested reviewers: dsfans2014, ouyangluwei163

Poem

A rabbit spots cards in a neat little row,
MIG slices now spread where the free devices grow.
UUIDs keep duplicates out of the game,
Scores still choose pairs by their topology name.
When cards are scarce, one card can still pack—
“Hop hop,” says the rabbit, “the fallback is back!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #2750 by spreading MIG allocations across cards, reducing duplicates, preserving fallback packing, and adding regression tests.
Out of Scope Changes check ✅ Passed The production and test changes are directly related to the MIG topology scheduling objectives in issue #2750.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: collapsing duplicate MIG candidates in NVIDIA topology scheduling.
✨ 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.

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 63.72% <100.00%> (+0.60%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/device/nvidia/device.go 96.52% <100.00%> (+0.48%) ⬆️

... and 13 files with indirect coverage changes

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

Comment thread pkg/device/nvidia/device_test.go
@mesutoezdil

Copy link
Copy Markdown
Contributor

/lgtm

@archlitchi archlitchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@hami-robot

hami-robot Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: archlitchi, Eshiv-Pandey

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

The pull request process is described 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

@hami-robot hami-robot Bot added the approved label Aug 25, 2026
@hami-robot
hami-robot Bot merged commit b0c21d9 into Project-HAMi:master Aug 25, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved kind/bug Something isn't working lgtm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MIG devices are allocated repeatedly on a single card in topology scheduling mode

3 participants