Skip to content

Release the weight-checker snapshot once compare passes - #37284

Open
yueming-yuan wants to merge 3 commits into
mainfrom
yueming/weight-checker-mmap-snapshot-main
Open

yueming-yuan wants to merge 3 commits into
mainfrom
yueming/weight-checker-mmap-snapshot-main

Conversation

@yueming-yuan

@yueming-yuan yueming-yuan commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

The WeightChecker snapshot is a host copy of every weight — tens of GB for a large model — and it stayed resident for the whole run even though compare is its only consumer. Two changes:

  1. Back the snapshot with a single mmap arena (alloc_mmap) instead of per-tensor .cpu() copies. The per-tensor copies are mostly below glibc's mmap threshold, so freeing them never shrinks RSS (on Grace/64K pages even malloc_trim reclaims nothing); one mmap region is returned to the OS deterministically by munmap.
  2. Release the snapshot (arena + views) once compare passes; a failed compare keeps it for debugging.

Verified on GB300 (DeepSeek-V4, 8 nodes): snapshot RSS returns to the OS after the first compare; unit tests cover the arena packing and release paths.

Port of #36561 (merged into sglang-miles) to main.


CI States

Latest PR Test (Base): ❌ Run #34829365272
Latest PR Test (Extra): ❌ Run #34829365024
Latest PR Test (AMD ROCm 10): ❌ Run #34829365286

snapshot_tensors = {}
for (name, param), offset in zip(named_params, offsets):
view = (
self._snapshot_arena[offset : offset + param.nbytes]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: make an abstractin similar to the BumpAllocator's API to avoid hand-compute offsets etc and a bit clearer

for _, param in named_params:
offsets.append(total)
total += (param.nbytes + align - 1) // align * align
self._snapshot_arena = alloc_mmap((max(total, align),), torch.uint8)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Publish the mmap arena only after the snapshot is fully built

self._snapshot_arena is assigned before any of the views are constructed or copied. If a later .view() or copy_() raises, _snapshot_tensors remains unset, but the fully prefaulted, model-sized mmap remains reachable from the long-lived checker. A retry must allocate another arena before replacing the old one, which can OOM. Please build the arena in a local variable and publish _snapshot_arena and _snapshot_tensors together only after every copy succeeds.

Found by Codex.

Bump-allocate the per-tensor views through a small arena allocator and
assign _snapshot_arena/_snapshot_tensors together at the end, so a copy
that raises mid-snapshot leaves no model-sized mmap held by the checker.
@yueming-yuan

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci label Sep 2, 2026
…r-mmap-snapshot-main

# Conflicts:
#	python/sglang/srt/utils/weight_checker.py
@yueming-yuan
yueming-yuan enabled auto-merge (squash) September 3, 2026 22:55
@Jiminator Jiminator closed this Sep 14, 2026
auto-merge was automatically disabled September 14, 2026 04:42

Pull request was closed

@Jiminator
Jiminator deleted the yueming/weight-checker-mmap-snapshot-main branch September 14, 2026 04:42
@alexnails
alexnails restored the yueming/weight-checker-mmap-snapshot-main branch September 14, 2026 05:46
@hnyls2002 hnyls2002 removed the run-ci label Sep 14, 2026
@hnyls2002 hnyls2002 reopened this Sep 14, 2026
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