Skip to content

feat(agent): checkpoint and restore POSIX CUDA VMM state - #218

Closed
galletas1712 wants to merge 2 commits into
feat/cuinterpose-host-carrierfrom
feat/cuinterpose-posix-lifecycle
Closed

galletas1712 wants to merge 2 commits into
feat/cuinterpose-host-carrierfrom
feat/cuinterpose-posix-lifecycle

Conversation

@galletas1712

@galletas1712 galletas1712 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Layer 9 of the eleven-PR cuinterpose stack #293, based on the host-carrier module in #292. Closed PR #214 is not in the active stack.

This PR checkpoints and restores actually shared POSIX-FD CUDA VMM allocations. It owns allocation eligibility and unicast topology; #292 owns the D2H/H2D host-carrier mechanics.

Ownership boundary

Allocation Checkpoint owner
Private VMM allocation, including POSIX-capable memory never exported or bound into tracked multicast Native CUDA checkpoint
Allocation actually exported/imported through the tracked POSIX sharing path Interposer
Allocation bound into tracked multicast Interposer; #219 marks the member shared
Legacy cuIpc* memory Native CUDA checkpoint

Export capability alone does not make an allocation shared. Private allocations remain mapped with their native handles intact when the interposer finishes preparation. The native driver remains responsible for saving and rebuilding their physical backing; this does not imply that GPU contents survive checkpoint automatically.

Only shared eligible creators advertise ALLOCATION_CONTENT and use host carriers. Imported allocations reference their canonical creator without duplicating content. Private records remain available for topology inspection, but no longer advertise CONTENT_ONLY; its protocol bit is reserved. Existing device-location, pinned-allocation, and exportability checks are retained. Unsupported exportable resources and live raw imports still fail preflight before destructive teardown.

Lifecycle

PREPARE_MULTICAST → SAVE_ALLOCATIONS → PREPARE_UNICAST

At this layer multicast preparation is a phase boundary; #219 supplies teardown. SAVE_ALLOCATIONS recovers handles only for shared creators with surviving mappings, copies their contents through #292, and advances all participants. PREPARE_UNICAST quiesces descriptor export, drains in-flight requests, and unmaps/releases only shared allocations. Private allocations are not temporarily retained, copied, unmapped, or released.

LOAD_ALLOCATIONS → RESTORE_UNICAST

Creators reconstruct shared backing, copy saved contents, restore mappings/access, and publish fresh descriptors under the original allocation IDs. The all-participant load barrier precedes importer reconstruction. #219 subsequently reconstructs multicast. Lifecycle failures remain fail-stop, and application-facing tracked VMM operations remain gated while preparation/restoration is in progress.

Validation

The ownership update extends the existing fake-driver lifecycle tests:

  • Mixed shared/private allocations: only shared bytes enter the carrier; private mappings remain present.
  • Private mapping whose application handle was released: preparation does not recover a temporary handle or copy content; retain-by-address works afterward.
  • Context-less creation and failed-copy cases explicitly export the allocations intended to exercise the interposer path.

Candidate 4100a48c72a3541ce547f4f4994d12682d475ab1 passes all 68 native fake-driver tests, including five lifecycle tests, with the configured ASan/UBSan instrumentation. The build used CUDA 13.1 headers, /usr/bin/gcc and /usr/bin/g++, cached GoogleTest, and a short SNAPSHOT_CONTROL_DIR. git diff --check and strict C syntax checks also pass. Logs: stack-private-vmm/pr218-final-tests.log.

The initial default-toolchain attempt could not link static libc/pthread; a subsequent long-path attempt exceeded the Unix-socket path limit. Both were corrected in the test environment without source changes. Real GPU validation of this exact candidate has not yet been run.

The existing 73-test sanitizer and three-test B200 results described in earlier revisions belong to historical stack head 0eae9c4f9b66093332f00a332afaf56048e1e64a; they are not validation of this ownership update.

Contribution notes

This updates the existing stack rather than creating a duplicate PR. AI assistance was used to prepare the implementation, tests, and description; the submitting human must review the changes and validation.

The full stack at exact #220 head 21008b50b93a9879a805665e331e777bb93abf49, including this fix, passed all 3 physical-GPU tests with 0 skips and 0 failures in 19.896 s on two B200 GPUs on nscale-dev, 2026-09-12 UTC. Compilation used the documented ALLOW_OLD_CUDA_HEADERS=1 override with CUDA 13.0 headers. This is full-stack GPU validation, not a standalone GPU run of #218. The restore-performance experiment's NIXL and driver changes are not part of this PR.

@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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

@copy-pr-bot

copy-pr-bot Bot commented Sep 11, 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.

@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 50e38ed to 74785a0 Compare September 11, 2026 06:10
@galletas1712
galletas1712 removed this pull request from stack #221 September 11, 2026 06:11
@galletas1712
galletas1712 changed the base branch from feat/cuinterpose-posix-tracking to feat/cuinterpose-host-carrier September 11, 2026 06:11
@galletas1712
galletas1712 added this pull request to stack #293 September 11, 2026 06:11
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 74785a0 to 487d95d Compare September 11, 2026 06:16
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 487d95d to dbbbf3c Compare September 11, 2026 06:21
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from dbbbf3c to 3a541d8 Compare September 11, 2026 06:41
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 3a541d8 to 078cc30 Compare September 11, 2026 08:31
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 078cc30 to 75b7679 Compare September 11, 2026 09:41
The shim now serves the coordinator lifecycle for allocations tracked by the
previous layer. Capture proceeds through PREPARE_MULTICAST,
SAVE_ALLOCATIONS, and PREPARE_UNICAST. At this layer multicast prepare is a
phase boundary. Allocation save recovers a creator handle from a surviving
mapping when necessary and preserves every supported exportable creator
device allocation through the host-carrier module in the parent change.
Never-exported creators are included as content-only allocations. Unicast
prepare quiesces peer export, drains in-flight requests, unmaps tracked
creator and importer mappings, and releases local driver handles while
retaining CPU records for CRIU.

Restore uses two unicast barriers. LOAD_ALLOCATIONS creates and fills fresh
exportable creator allocations through the content module, then rebuilds
creator mappings, access grants, and export-cache entries. Only after every
participant has published its creator endpoints does RESTORE_UNICAST let
importers fetch fresh descriptors, import the same physical allocations,
and rebuild their mappings and access. Participants with no allocation
content still advance through every lifecycle operation.

Eligibility remains lifecycle policy: every tracked creator allocation backed
by pinned device memory preserves content. Because the tracking layer supports
exactly POSIX-FD exportability, this covers every currently supported
exportable physical allocation. Private allocations remain native, and the
coordinator refuses unsupported nonzero exportable types before this sequence.
Application-facing tracked VMM calls return CUDA_ERROR_NOT_READY while the
shim is outside its active phase, and any partial rebuild fails closed.

lifecycle_preload_test drives this process and a forked importer through the
real coordinator over the fake driver. It covers exported and never-exported
allocations, missing host registration after restore, live raw-import
refusal, context-less allocations, and failed content-copy cleanup. Real-GPU
coverage follows in its own change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Signed-off-by: Schwinn Saereesitthipitak <schwinns@nvidia.com>
@galletas1712
galletas1712 force-pushed the feat/cuinterpose-posix-lifecycle branch from 75b7679 to 8f788ad Compare September 11, 2026 10:08
Co-authored-by: OpenAI <noreply@openai.com>
Signed-off-by: Schwinn Saereesitthipitak <schwinns@nvidia.com>
@galletas1712

Copy link
Copy Markdown
Contributor Author

Superseded by the replacement 13-PR C-frontend/Rust-backend cuinterpose draft stack: https://github.com/ai-dynamo/snapshot/stack/339 (#326#338), tracking approved proposal #295. The new stack preserves one reviewable stage per PR, with tests collected in #338 and the design in #337. PageBroker transfer changes remain a separate dependency. Closing this older C implementation; retaining its branch and discussion for reference.

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.

2 participants