Skip to content

perf(rm): replace per-iteration sort in distributedAlloc with a min-heap - #1826

Merged
henry118 merged 2 commits into
NVIDIA:mainfrom
jonathan-meiri:optimize-distributedalloc-heap
Sep 3, 2026
Merged

henry118 merged 2 commits into
NVIDIA:mainfrom
jonathan-meiri:optimize-distributedalloc-heap

Conversation

@jonathan-meiri

Copy link
Copy Markdown

Summary

Follow-up optimization stacked on #1788. Until #1788 lands, this PR's cumulative diff includes that commit too — the new work here is in the second commit (the heap refactor). Not for review until #1788 lands.

Replaces the per-iteration sort.Slice in distributedAlloc with a min-heap keyed by (used, pickedFrom). Brings the loop from O(n² log n) to O(n log m) where n is replicas requested and m is the number of physical GPUs touched in this allocation. Same correctness as #1788; same tests pass.

Practically, n and m are small in real configurations and the wall-clock impact is invisible — this is structural cleanliness, not a hot-path speedup.

Opened as draft so it doesn't enter the review queue alongside #1788. Happy to mark it ready as a separate follow-up after #1788 lands, or fold the change into #1788 if that's preferred.

Contributed by @Meiri28 on behalf of @runatom-ai.

@copy-pr-bot

copy-pr-bot Bot commented Jun 2, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 82b1b23 to b9da143 Compare June 2, 2026 08:16
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from b9da143 to 21cd040 Compare June 30, 2026 15:35
@jonathan-meiri
jonathan-meiri marked this pull request as ready for review June 30, 2026 19:10
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch 3 times, most recently from 8333b12 to 5efcd18 Compare July 1, 2026 11:02
@jonathan-meiri

Copy link
Copy Markdown
Author

Hi @rajatchopra — following up on your comment in #1788 ("Lets attack the loop optimization in #1826 next"). This PR is out of draft and ready for review: a single commit with the heap-based O(n log m) refactor of distributedAlloc. Would appreciate your thoughts when you have a moment.

@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 5efcd18 to 2319fe5 Compare July 14, 2026 12:50
@rajatchopra

Copy link
Copy Markdown
Contributor

Heap logic looks good. Though this PR must wait for #1621 first. Will need a rebase after that.

@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 2319fe5 to 6848b06 Compare July 22, 2026 08:24
@jonathan-meiri

Copy link
Copy Markdown
Author

Rebased on top of #1621 (now merged). The heap now sits on top of the new greedyAlloc / replicaComparator structure — both distributed and packed policies get the O(n log m) improvement. Existing tests pass unchanged.

Ready for another look when you have a moment, @rajatchopra.

@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch 2 times, most recently from 06c33eb to 36e7ad1 Compare July 28, 2026 09:45
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch 2 times, most recently from 954879b to 2af157d Compare August 6, 2026 13:12
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 2af157d to 3a62327 Compare August 12, 2026 17:02
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 3a62327 to 8b0a351 Compare September 1, 2026 08:10
@henry118

henry118 commented Sep 1, 2026

Copy link
Copy Markdown
Member

@jonathan-meiri Do you have the benchmark data that shows the improvement?

@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch 4 times, most recently from ca923f7 to 3be20fb Compare September 2, 2026 06:19
@jonathan-meiri

Copy link
Copy Markdown
Author

@henry118 The improvement is real, added BenchmarkGreedyAlloc (3be20fb),
same signature so it runs on main too for a direct before/after:

  • n=64 (8 GPUs ×8): 137µs → 18µs (7.7×)
  • n=128 (8 ×16): 518µs → 36µs (14×)

plus ~10× fewer allocations. To be clear on scope: this isn't a hot path (runs once per pod admission), so it's not a latency fix. The change came out of @rajatchopra's suggestion on #1788 to do one sort instead of N

@henry118

henry118 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Thanks @jonathan-meiri, numbers look legit.

Allocs dropping is good. Raw us savings won't be noticeable in practice, but the alloc/GC reduction is worth it on its own.

Please rebase and sign off the last commit.

Meiri28 and others added 2 commits September 3, 2026 07:20
Follow-up on top of NVIDIA#1621, which introduced the shared greedyAlloc loop
with a pluggable replicaComparator (distributed vs packed). The loop
still sorts the full candidate slice inside the allocation loop, paying
O(n log n) per iteration for n iterations and giving O(n² log n) overall.

Since all annotated replicas from the same underlying physical device
share the same sort key, sorting at the replica granularity is wasted
work — only m (the number of distinct physical devices contributing
candidates) needs to be reordered.

Refactor greedyAlloc to bucket candidates by their underlying physical
device into a small gpuAllocState per device, holding a shared
*replicaCount, the pickedFrom counter, and the remaining candidate IDs.
A gpuPriorityQueue defers to the caller-supplied replicaComparator on
allocated() for primary ordering and to pickedFrom for the tie-break
(unchanged semantics). Each iteration pops the best device, takes one
of its remaining replicas, updates counters, and pushes it back if any
remain.

Total cost drops to O(n log m). Both allocation policies (distributed
and packed) benefit; no behavior change — the existing test suite
(TestDistributedAlloc, TestPackedAlloc, TestPackedVsDistributedContrast,
TestDistributedAlloc_PartiallyAllocated_DistributesAcrossDistinctGPUs,
etc.) passes unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: runatom-ai <258621014+runatom-ai@users.noreply.github.com>
Signed-off-by: Jonathan Meiri <33288957+Meiri28@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: runatom-ai <258621014+runatom-ai@users.noreply.github.com>
Signed-off-by: Jonathan Meiri <33288957+Meiri28@users.noreply.github.com>
@jonathan-meiri
jonathan-meiri force-pushed the optimize-distributedalloc-heap branch from 3be20fb to 498aba4 Compare September 3, 2026 04:20
@jonathan-meiri

Copy link
Copy Markdown
Author

@henry118 Done, rebased on latest main and signed off the benchmark commit (DCO green).
Thanks for the review!

@henry118

henry118 commented Sep 3, 2026

Copy link
Copy Markdown
Member

/ok to test 498aba4

@henry118
henry118 merged commit 3c6be40 into NVIDIA:main Sep 3, 2026
12 checks passed
@jonathan-meiri

Copy link
Copy Markdown
Author

Thanks for the review and merge, @henry118 🙏

FYI the follow-up #1936 (a spread allocation policy) builds directly on this greedyAlloc/comparator structure, I just took it out of draft now that this PR landed. No rush at all, just flagging the connection while it's fresh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants