bindings/rust: add prepMemView/releaseMemView to the C API and nixl-sys (#2060)
Needed for the LPU backend: `prepMemView` resolves a registered buffer into the `nixlMemViewH` that the device-side send and receive calls take as input on the GPU. Without a Rust binding the backend cannot prepare its data-plane views, so the whole device data path is unreachable. ## What? Binds `prepMemView` / `releaseMemView` into the Rust C API layer and `nixl-sys`. - C API: `prep_mem_view_local` / `_remote` / `release_mem_view`, plus `create_remote_dlist` / `_add_desc` / `_destroy_remote_dlist`, with matching `stubs.cpp` forwarders. - nixl-sys: `Agent::prep_mem_view_local` / `_remote` returning a `MemView` that releases on `Drop`, and `RemoteDescList` / `RemoteDescriptor` beside `RegDescList` / `XferDescList`. - Four tests in `tests/mem_view.rs`: local and remote happy paths, unknown remote agent, all-null-agent list. Helpers shared with `tests.rs` live in `tests/common/mod.rs`. ## Why? The device API is GPU-initiated: `prepMemView` returns the `nixlMemViewH` a kernel passes to `nixlPut` or `nixlSend`. Its consumers so far have been CUDA C++, where host and device code share one program and a C boundary buys nothing, so it was never bound. It is needed once Rust owns the agent and view lifecycle while a thin CUDA shim launches the kernels. ## How? **The remote overload binds `nixl_remote_dlist_t`, not a single agent name.** A view can span peers: `nixl_ep` puts several agents in one list, using `nixl_null_agent` for unaddressed ranks so descriptor indices stay aligned with rank numbers (`examples/device/ep/csrc/nixl_ep.cpp:1328-1333`). **`prep_mem_view_*` are `unsafe`.** A view holds the registration handles of its buffers and is stored for the lifetime of the endpoint alongside them, so a lifetime bound would make the owning struct self-referential. `RemoteDescList` carries no lifetime: `nixl_capi_remote_dlist_add_desc` constructs a `nixlRemoteDesc` by value with a `std::string` agent name and `nixlDescList` stores `std::vector<T>`, so nothing borrows once the call returns. **The tests are gated on a CUDA toolkit.** They allocate VRAM, so `build.rs` probes `CUDA_PATH`, `CUDA_HOME`, then `/usr/local/cuda` in turn, and compiles them only if it finds one; a build without CUDA links no CUDA symbols. With a toolkit but no device they skip at run time. **`test_prep_mem_view_remote` is opt-in behind `NIXL_TEST_DEVICE_LANE=1`.** It is the only one needing a device-capable RDMA lane, which UCX offers only over accelerated IB; without one it fails at `ucp_device.c: lane not found for element 0`, which no up-front check can predict. Gating it rather than skipping on failure keeps a real regression a failure. ## Testing 104 tests pass on `cargo test` — 96 in `tests.rs`, 4 in `mem_view.rs`, 4 in `test_sync_manager.rs` — on UCX 1.21 with a CUDA device, against `libnixl` built from this branch's base. Three of the four memory-view tests exercise the path by default; the fourth was confirmed to run and pass with `NIXL_TEST_DEVICE_LANE=1`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Rust support for preparing local and remote memory views. * Added remote buffer descriptors, descriptor lists, and memory-view lifecycle management. * Added CUDA toolkit detection for GPU-enabled builds. * **Bug Fixes** * Improved error handling for invalid memory-view and remote descriptor operations. * **Tests** * Added CUDA-based local and remote memory-view integration tests. * Documented CUDA, RDMA, and NIXL test prerequisites and opt-in behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Shahaf Kiselnik <smeir@nvidia.com>
S
ShahafMeir committed
6d855fc135f8c56340a078751769f92f74cf57ee
Parent: e1cbabc
Committed by GitHub <noreply@github.com>
on 8/18/2026, 12:51:17 PM