feat(data_plane): add Mooncake GDR support - #3501
Conversation
8fae9a1 to
6e39a2b
Compare
6e39a2b to
d2edefb
Compare
|
/ok to test d2edefb |
d2edefb to
31f9117
Compare
|
/ok to test 31f9117 |
31f9117 to
5bdc8e7
Compare
|
/ok to test 5bdc8e7 |
Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
480ccc7 to
1376417
Compare
Self-review with
|
|
/ok to test 1376417 |
The check ran after `tq.kv_batch_put`, by which point TQ has already written the rows into Mooncake and called `notify_data_update`, so raising could not prevent the fallback it was meant to catch. It only denied the caller its `KVBatchMeta` — and at the one call site where it was reachable, `column_io.write_columns` via `TQWorkerMixin._write_back`, there is no rollback, so the committed rows were left orphaned. It was also unreachable as a genuine failure. The pre-PUT check already tests TQ's own routing condition (`use_gdr and _gdr_staging is not None`), and `_put_tensors_gdr` then calls `lazy_init()` unconditionally, which sets `_initialized` or raises. The only way to trip the post-PUT check was an upstream rename of a TransferQueue private attribute, which would have aborted a healthy GDR run with a message describing a fallback that never happened. The pre-PUT check is kept: it runs before anything is written, so it still fails closed on a real CPU-RDMA fallback, which is what this commit's predecessor set out to do. Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
| - **`mooncake_cpu`** — Mooncake's RDMA-only transfer engine. By default, | ||
| tensors transfer through registered CPU staging. Set | ||
| `mooncake_cpu.use_gdr: true` to let CUDA-initialized clients use |
There was a problem hiding this comment.
Do you think we should change the name?
Option one
- moocnake
- cpu
- gdr
Option 2
- mooncake_cpu
- mooncake_gdr
There was a problem hiding this comment.
This sounds reasonable to me. But maybe we should have a separate renaming PR since it touches a lot of files.
|
@zyzhou5 awesome PR! |
|
@zyzhou5 I remember you mentioned we need to some changes in both put and get side to avoid unnecessary H2D or D2H. I think the best we can do is Have we achieved that? |
`test_gdr_tensor_put_is_confirmed_once_and_never_falls_back` was added without updating the section, which claims to audit every test function under `tests/unit/data_plane/`. Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
…fer_mb The knob reserves its full size in HBM per active GDR client for the life of the run, and it has a hard lower bound: below the largest per-sample, per-field payload TransferQueue splits the value into chunk sub-keys, and a GDR read of a value written by a CPU-RDMA client then fails on an assertion inside TransferQueue that carries no message. Sizing also has a knee. An aggregate fetch larger than the buffer is split into groups that transfer one at a time, so lowering it multiplies the group count and costs throughput on both the CPU and GDR paths, while raising it above the default buys little and costs HBM linearly. GDR's gain shows up only once the buffer is large enough that group count is not the bottleneck. None of this was stated anywhere a user would look. The exemplar config is where the value actually gets set, so the guidance goes there; the transfer mechanics stay in nemo_rl/data_plane/README.md. Also aligns the two GDR comments to the block's existing column. Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
not yet... the PUT operation starts from CPU so there is an extra H2D. The PUT inference-side fix would need a bigger change so should be placed in another PR. Created an issue to track it #4051. |
The flat `data_plane.use_gdr` spelling never shipped — `git log -S"use_gdr"` at this branch's base returns no commits, and it appears nowhere on main — so no merged config could ever trip this check. Making it fire also required declaring `use_gdr` and `gdr_staging_buffer_mb` as `NotRequired` on `DataPlaneConfig`, which advertises them to any reader as legal top-level keys: the opposite of the intent. It also left two policies for one class of mistake three lines apart, since the pre-nesting flat sizing keys are silently ignored. `backend_config` now has one rule: only the nested block is read. Removes the two declarations, `_FIRST_GDR_FLAT_KEYS`, the raise, the two docstring passages, the README sentence, and the two tests that pinned it. Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
`setup_data_plane` takes `DataPlaneRuntimeConfig`, which is
`DataPlaneConfig | LocalDataPlaneConfig`. The guard subscripted `cfg`
directly, so a `LocalDataPlaneConfig` — a BaseModel, not a mapping — would
raise `TypeError` before ever reaching `build_data_plane_client`.
The guard was written when `setup_data_plane` still took the narrower
`DataPlaneConfig`; main widened the parameter, and the two changes never
touched the same lines, so the rebase merged cleanly and broke the
semantics. `pyrefly` caught it:
Argument `LocalDataPlaneConfig | TypedDict[DataPlaneConfig]` is not
assignable to parameter `cfg` with type `TypedDict[DataPlaneConfig]`
Narrow with `isinstance` first, matching how `factory.py` handles the same
union. The local plane has no TQ and no mooncake, so it has no GDR to order
against a CUDA context.
Signed-off-by: Zeyu Zhou <zezhou@nvidia.com>
|
/ok to test 9896a67 |
What does this PR do?
Adds the minimal NeMo-RL configuration plumbing needed to enable TransferQueue v0.1.9's Mooncake GPUDirect RDMA (GDR) path. TransferQueue v0.1.9 is already pinned on current
mainby #3423.data_plane.use_gdr; omitting it defaults tofalse, so existing recipes are unchanged;protocol: rdmaanduse_gdr: trueto Mooncake when GDR is enabled;Persistent queued Mooncake objects remain in CPU RAM. GDR changes the CUDA client's transfer path by using a registered GPU staging buffer; it does not turn the persistent queue into GPU storage.
User configuration
Relationship to #2935
This PR does not stack on or require #2935. The TQ dependency update is already on
mainvia #3423. The runtime-environment cleanup proposed by #2935 is separate and is not included here.Relationship to #3837
To use GDR on the put side instead of falling back to CPU RDMA, we need #3837 to get merged since TQ must be initialized inside the generation worker after CUDA is initialized so it selects GDR for PUTs.
E2E test