feat(gms): introduce VMMDevice abstraction for XPU (Phase 1) - #9788
Conversation
WalkthroughThis PR extends the GPU Memory Service to support configurable VMM (Virtual Memory Management) device kinds. It introduces a vendor-neutral device abstraction protocol, defines a device-type enum with a factory pattern, and threads device-kind parameters through the server, client, CLI, and snapshot utilities, enabling selection between CUDA and other backends while enforcing CUDA-only behavior where required. ChangesVMM Device Kind Support
🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
lib/gpu_memory_service/client/memory_manager.py (1)
39-54: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy liftUse
self._vmmas the execution path instead of keeping CUDA helpers as the active path.The class now captures
device_kind/_vmm, but core operations still execute via CUDA-specific functions. This keeps behavior CUDA-coupled and undercuts the new abstraction.Proposed starting point
- cuda_ensure_initialized() - self.granularity = cumem_get_allocation_granularity(device) + self._vmm.ensure_initialized() + self.granularity = self._vmm.get_allocation_granularity(device)Then progressively switch map/unmap/import/release/access/sync/validate call sites to
self._vmm.*methods to keep backend dispatch consistent end-to-end.Also applies to: 166-190
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/gpu_memory_service/client/memory_manager.py` around lines 39 - 54, The code imports and directly calls CUDA-specific helpers (cumem_map, cumem_unmap, cumem_import_from_shareable_handle_close_fd, cumem_release, cumem_set_access, cuda_synchronize, cuda_validate_pointer, etc.) instead of routing operations through the VMM abstraction captured on the instance; update all call sites in memory_manager.py (including the block around lines 166–190) to invoke the corresponding methods on self._vmm (e.g., self._vmm.map, self._vmm.unmap, self._vmm.import_from_shareable_handle_close_fd, self._vmm.release, self._vmm.set_access, self._vmm.synchronize, self._vmm.validate_pointer or whatever the VMM API provides) so backend dispatch is consistent end-to-end and remove or stop using the CUDA-specific helpers in this module.lib/gpu_memory_service/client/torch/allocator.py (1)
125-131:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winValidate
device_kindwhen reusing an existing tag state.Both reuse paths check socket/device but not backend kind, so a caller can request a different
device_kindand silently get the previous manager.Suggested fix
- if state.socket_path != socket_path or state.device != device: + if ( + state.socket_path != socket_path + or state.device != device + or state.manager.device_kind != device_kind + ): raise RuntimeError( f"GMS allocator tag={tag} was initialized for " - f"{state.socket_path} on device {state.device}, not {socket_path} " - f"on device {device}" + f"{state.socket_path} on device {state.device} " + f"(device_kind={state.manager.device_kind.value}), not {socket_path} " + f"on device {device} (device_kind={device_kind.value})" )(Apply the same check in
get_or_create_scratch_manager.)Also applies to: 203-209
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/gpu_memory_service/client/torch/allocator.py` around lines 125 - 131, The reuse check only compares socket_path and device but not backend kind, so update the reuse guard to also validate state.device_kind matches the requested device_kind and raise a RuntimeError with the same style if it differs; apply this change in the allocator reuse branch shown (the block that raises for tag mismatch) and make the identical addition in get_or_create_scratch_manager (the reuse path around lines 203-209) so callers cannot silently get a manager for a different device_kind.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/gpu_memory_service/cli/server.py`:
- Around line 21-23: The CLI currently calls the CUDA-only helper list_devices
to discover devices (references: list_devices) even when the user passed a
non-CUDA --device-kind (references: VMMDeviceType and the CLI device-kind
parsing logic), causing incorrect/empty spawn behavior; change the discovery to
be backend-aware by switching on the parsed device-kind (use VMMDeviceType
enum/value) and calling the appropriate backend discovery routine (or returning
an empty/placeholder list and letting the backend report the unsupported-kind
error) instead of list_devices for non-CUDA kinds, and update all occurrences
where list_devices is used (the device discovery blocks around the CLI parsing
and the spawn/pre-check paths) to this backend-switching approach so device
discovery matches --device-kind.
In `@lib/gpu_memory_service/cli/snapshot/loader.py`:
- Around line 21-23: The loader currently always calls the CUDA-specific
list_devices despite parsing GMS_DEVICE_KIND; update the device enumeration to
branch on the parsed device kind (VMMDeviceType) instead of unconditionally
calling list_devices. In loader.py replace direct list_devices usage with a
dispatch that: checks the device_kind value (VMMDeviceType.CUDA,
VMMDeviceType.ROCm/ROCM, etc.), calls the appropriate enumeration helper for
each kind (add or import a ROCm/other list function if missing), and raises/logs
a clear error for unsupported kinds; apply this change to all places where
list_devices is used in this module (imports at top and usages around the
current discovery logic referenced by VMMDeviceType and GMS_DEVICE_KIND).
In `@lib/gpu_memory_service/cli/snapshot/saver.py`:
- Around line 18-20: The code parses GMS_DEVICE_KIND but always calls
list_devices (CUDA); update the discovery logic in saver.py to branch on
GMS_DEVICE_KIND (the parsed value) using the VMMDeviceType enum: if
GMS_DEVICE_KIND == VMMDeviceType.CUDA, call list_devices as currently done; for
other VMMDeviceType values call the appropriate backend discovery helper (or a
generic discovery API provided by your VMM layer) instead of list_devices, and
if no backend-discovery exists, raise an explicit error/NotImplementedError so
the failure is clear. Ensure you change the code paths where list_devices is
used (references near the current call) to use this conditional logic and keep
VMMDeviceType and GMS_DEVICE_KIND as the selectors.
In `@lib/gpu_memory_service/server/allocations.py`:
- Around line 72-77: The init currently calls CUDA helpers directly
(cuda_ensure_initialized and cumem_get_allocation_granularity) instead of using
the VMM abstraction; update the constructor to route these operations through
the VMM returned by get_vmm_device(device_kind) (self._vmm) so non-CUDA backends
can implement their own init/granularity logic—replace direct calls to
cuda_ensure_initialized() and cumem_get_allocation_granularity(device) with
self._vmm.initialize() (or equivalent VMM init method) and
self._vmm.get_allocation_granularity(device) (or VMM property/method) and make
the same change for the allocation-related calls referenced around lines 81-85
to consistently use self._vmm instead of CUDA helpers.
---
Outside diff comments:
In `@lib/gpu_memory_service/client/memory_manager.py`:
- Around line 39-54: The code imports and directly calls CUDA-specific helpers
(cumem_map, cumem_unmap, cumem_import_from_shareable_handle_close_fd,
cumem_release, cumem_set_access, cuda_synchronize, cuda_validate_pointer, etc.)
instead of routing operations through the VMM abstraction captured on the
instance; update all call sites in memory_manager.py (including the block around
lines 166–190) to invoke the corresponding methods on self._vmm (e.g.,
self._vmm.map, self._vmm.unmap, self._vmm.import_from_shareable_handle_close_fd,
self._vmm.release, self._vmm.set_access, self._vmm.synchronize,
self._vmm.validate_pointer or whatever the VMM API provides) so backend dispatch
is consistent end-to-end and remove or stop using the CUDA-specific helpers in
this module.
In `@lib/gpu_memory_service/client/torch/allocator.py`:
- Around line 125-131: The reuse check only compares socket_path and device but
not backend kind, so update the reuse guard to also validate state.device_kind
matches the requested device_kind and raise a RuntimeError with the same style
if it differs; apply this change in the allocator reuse branch shown (the block
that raises for tag mismatch) and make the identical addition in
get_or_create_scratch_manager (the reuse path around lines 203-209) so callers
cannot silently get a manager for a different device_kind.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 642eaa55-5176-420f-a960-98912628dd7e
📒 Files selected for processing (15)
lib/gpu_memory_service/cli/args.pylib/gpu_memory_service/cli/runner.pylib/gpu_memory_service/cli/server.pylib/gpu_memory_service/cli/snapshot/loader.pylib/gpu_memory_service/cli/snapshot/saver.pylib/gpu_memory_service/client/memory_manager.pylib/gpu_memory_service/client/torch/allocator.pylib/gpu_memory_service/common/vmm/__init__.pylib/gpu_memory_service/common/vmm/cuda_utils.pylib/gpu_memory_service/common/vmm/device.pylib/gpu_memory_service/server/allocations.pylib/gpu_memory_service/server/gms.pylib/gpu_memory_service/server/rpc.pylib/gpu_memory_service/snapshot/storage_client.pytests/report_pytest_markers.py
|
@dzier, per meeting discussion pls help involve gms team to check if VMMDevice abstraction proposal is OK for cuda. Then we can plug in xpu. |
2909031 to
1461d24
Compare
fc11c5e to
578e84d
Compare
|
/ok to test 578e84d |
|
/ok to test d01df1c |
hhzhang16
left a comment
There was a problem hiding this comment.
nit: I find it a bit confusing how the "initialization"/what it represents in init_vmm and vmm.ensure_initialized are different
|
/ok to test 4decbe1 |
|
@GuanLuo @hhzhang16 pls kindly have a look at two commits as well. Please also trigger ok test if no concern. thx |
|
/ok to test e11e37a |
|
/ok to test 1819dc7 |
Hi @GuanLuo @hhzhang16 , it seems CI passed with 32 skipped ,could you pls help review and check the next step? thx |
Hi @hhzhang16, I rebased it against latest main again. Please help check /ok test. thx |
Add a device-agnostic Virtual Memory Management (VMM) abstraction layer that decouples GMS from CUDA-specific driver calls. The vendor-neutral VMMDevice Protocol abstracts the per-device virtual memory management surface.This enables future XPU (and other vendor) backends without modifying consumer code. All existing `--device-kind cuda` deployments should continue to work. New modules: - common/vmm/__init__.py: VMMDeviceType enum, get_vmm_device() factory - common/vmm/device.py: VMMDevice Protocol (runtime-checkable, 20 methods) - common/vmm/cuda_utils.py: CudaVMM class wrapping existing CUDA helpers Refactored consumers (all now use self._vmm.* instead of direct cumem_*): - client/memory_manager.py: VA reserve/map/unmap/remap lifecycle - server/allocations.py: physical memory allocate/export/release - snapshot/backends/pinned_host.py: PinnedCopySlot stream + memcpy ops - snapshot/backends/nixl_staging.py: staging session device context - snapshot/disk.py: DeviceToFileWriter pinned buffer management CLI plumbing (--device-kind cuda|xpu): - cli/args.py, cli/server.py, cli/runner.py - cli/snapshot/loader.py, cli/snapshot/saver.py Guards for CUDA-only torch integration: - client/torch/allocator.py: NotImplementedError for non-CUDA mempool Utility: - common/utils.py: align_to_granularity() extracted (pure math, no device dep) Tests: - test_snapshot_loader.py: updated monkeypatches for VMMDevice mock - test_snapshot_nixl_staging.py: updated for vmm= kwarg and new signatures CUDA path is unchanged: CudaVMM delegates to the same standalone helpers. VMMDeviceType.XPU is defined but raises NotImplementedError (phase 2). Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
fix test_runtime_flows.py since its monkeypatch fixture still patched non-existent module-level function names. - Add tests/_fake_vmm.py: shared FakeVMM(VMMDevice) implementing all abstract methods with in-memory counters and os.pipe() for FD simulation. - test_runtime_flows.py: replace dead monkeypatch.setattr(module, "cumem_*", ...) calls with singleton injection via monkeypatch.setattr(_vmm_module, "_vmm_instance", FakeVMM()). - test_snapshot_loader.py: replace inline _FakeVMM with shared FakeVMM. - test_snapshot_nixl_staging.py: replace inline _FakeVMM with shared FakeVMM. Signed-off-by: Zhan Xue <zhan.xue@intel.com>
- Add _detect_device_type() that probes torch.cuda availability at runtime (priority: CUDA > Other Device > fallback CUDA). - Make get_vmm() and get_vmm_device_type() lazily call init_vmm(_detect_device_type()) on first access when singleton is unset - Explicit init_vmm() from CLI --device-type still takes priority (runs before any get_vmm() call) - Add test_integration_helper_without_explicit_init_vmm verifying that constructing helpers without pre-seeding the singleton works This makes both CUDA and Othe Device paths work without explicit init_vmm(): - CUDA-only systems: auto-detected - Other-Device-only systems: auto-detected - Mixed systems: defaults to CUDA; CLI --device-type device overrides Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
- revert "torch.cuda.synchronize(manager.device)" with "torch_device().synchronize(manager.device)". - calling sequence adjusted in init_vmm() - revert _child_command - removed the unused device_type Signed-off-by: Zhan Xue <zhan.xue@intel.com>
|
/ok to test cf51474 |
|
Hi @hhzhang16 @GuanLuo , could you pls share if any issue blocks merging this PR? As to reduce the continuous rebase efforts, could you pls check if we can merge it now? thx |
nnshah1
left a comment
There was a problem hiding this comment.
unblocking - changes focused on gpu memory service - and @hhzhang16 has approved.
Overview:
GMS XPU Enablement Phase 1: add a device-agnostic VMM (Virtual Memory Management) abstraction layer. All existing CUDA paths should be not unchanged. All existing
--device-kind cudadeployments should continue to work.VMMDeviceType.XPU defined but raises NotImplementedError. The vendor-neutral VMMDevice Protocol abstracts the per-device virtual memory management surface.
Please refer to https://github.com/zxue2/dynamo/blob/enable_gms_xpu/lib/gpu_memory_service/GMS_MULTI_DEVICE.md
Details:
VMM abstraction layer:
- common/vmm/device.py: VMMDevice Protocol
- common/vmm/init.py: VMMDeviceType enum + get_vmm_device() factory
- common/vmm/cuda_utils.py: existing cuda_utils relocated with CudaVMM
class implementing VMMDevice via delegation to the module-level
CUDA driver helpers
Server-side:
- cli/args.py: --device-kind argument (default: "cuda")
- cli/server.py: forward --device-kind to spawned processes
- cli/runner.py: pass device_kind to GMSRPCServer
- server/rpc.py -> server/gms.py -> server/allocations.py: pass
device_kind through to GMSAllocationManager which instantiates
the appropriate VMMDevice.
Client-side:
- client/memory_manager.py: accept device_kind, store VMMDevice
instance, expose device_kind property.
- client/torch/allocator.py: _ensure_callbacks_initialized and
_create_mem_pool accept device_kind; gms_use_mem_pool guards
against non-CUDA backends with NotImplementedError.
get_or_create_gms_client_memory_manager and
get_or_create_scratch_manager forward device_kind.
XPU path correctly raises NotImplementedError at factory, allocator,
and mem_pool levels. XPU implementation will be added in Phase 2.
Where should the reviewer start?
Please check if VMM abstraction is suitable for CUDA and multi-device.
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
Release Notes
--device-kindCLI option to configure GPU memory management backend selection