From 0ade29c6694dad3ff6278c7b1c8f812bb5eec36b Mon Sep 17 00:00:00 2001 From: Oseltamivir <58582368+Oseltamivir@users.noreply.github.com> Date: Wed, 28 Oct 2026 20:26:11 +0800 Subject: [PATCH] CollectiveX: give h200-dgxc DeepEP V2 its RDMA rate from the registry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vLLM v0.32.0 image does not ship ibstat, so DeepEP V2's SM model read a scale-out rate of 0 on h200-dgxc and normal-mode EP16 died with ZeroDivisionError in get_theoretical_num_sms. The registry now sets rdma_gbs to 50 GB/s, the value the ibstat probe derives from a 400 Gb/s ConnectX-7 port, as the EFA pools already do. vLLM v0.32.0 镜像不包含 ibstat,导致 h200-dgxc 上 DeepEP V2 的 SM 模型读到的 scale-out 速率为 0, normal 模式 EP16 在 get_theoretical_num_sms 中因 ZeroDivisionError 失败。注册表现在将 rdma_gbs 设为 50 GB/s(即 ibstat 探测从 400 Gb/s ConnectX-7 端口得出的值),与 EFA 资源池的做法一致。 --- collectivex/bench/ep_deepep_v2.py | 8 ++++---- collectivex/configs/platform_config.json | 3 ++- collectivex/docs/methodology.md | 11 ++++++----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/collectivex/bench/ep_deepep_v2.py b/collectivex/bench/ep_deepep_v2.py index d011ca512c..e6a7472752 100644 --- a/collectivex/bench/ep_deepep_v2.py +++ b/collectivex/bench/ep_deepep_v2.py @@ -260,10 +260,10 @@ def create_buffer(self, spec): # model, get_theoretical_num_sms(num_experts, num_topk), and combine reuses the handle's # count; num_qps follows from the SM count. The call below is the dispatch's own (same # cached arguments), so the recorded count is the one the kernels run with. The model - # reads the scale-out rate from ibstat, which cannot see EFA: there the hybrid branch would - # divide by zero, so the registry's per-GPU rate (COLLX_RDMA_GBS, set on EFA pools only) - # stands in and the result is passed explicitly. With overlap off the model's own count - # (10-26 SMs on these pools) is raised to 64 either way. + # reads the scale-out rate from ibstat, which cannot see EFA and is absent from the vLLM + # image: there the hybrid branch would divide by zero, so the registry's per-GPU rate + # (COLLX_RDMA_GBS) stands in and the result is passed explicitly. With overlap off the + # model's own count (10-26 SMs on these pools) is raised to 64 either way. rdma_gbs = float(os.environ.get("COLLX_RDMA_GBS") or 0) if rdma_gbs: self.num_sms = int(self.buffer.get_theoretical_num_sms( diff --git a/collectivex/configs/platform_config.json b/collectivex/configs/platform_config.json index aeb6b35462..e8c61cf069 100644 --- a/collectivex/configs/platform_config.json +++ b/collectivex/configs/platform_config.json @@ -42,7 +42,8 @@ }, "network": { "rdma_devices": "mlx5_0,mlx5_1,mlx5_2,mlx5_3,mlx5_4,mlx5_5,mlx5_6,mlx5_7", - "rdma_relaxed_ordering": 1 + "rdma_relaxed_ordering": 1, + "rdma_gbs": 50 } }, "b200-nscale": { diff --git a/collectivex/docs/methodology.md b/collectivex/docs/methodology.md index 1cc6f3298d..36c16aaef6 100644 --- a/collectivex/docs/methodology.md +++ b/collectivex/docs/methodology.md @@ -166,10 +166,11 @@ instead of upstream's and vLLM's automatic 65/129, which exhaust the per-NIC QP (`ibv_create_qp` ENOMEM in `ncclDevCommCreate`; 49x16 initializes, 65x16 does not). The 64-SM kernels ask for 64 x 16 + 1 QPs and are capped at that allocation, so the hybrid channels share 32 data QPs plus one notify QP (`library_config.num_allocated_qps`, `num_qps`). DeepEP's SM model reads -the scale-out rate from an `ibstat` probe that cannot see EFA, and in hybrid mode divides by it, so -on the EFA pools the registry's `network.rdma_gbs` supplies the per-GPU rate and the resulting count -is passed explicitly (`library_config.sm_model_rdma_gbs`). Elsewhere the count is left to DeepEP, as -vLLM leaves it. With overlap off the model's own 10-26 SMs are raised to 64 either way. +the scale-out rate from an `ibstat` probe that cannot see EFA and that the vLLM image does not ship, +and in hybrid mode divides by it, so on the EFA pools and on h200-dgxc the registry's +`network.rdma_gbs` supplies the per-GPU rate (50 GB/s on h200-dgxc, the value the probe reads from a +400 Gb/s ConnectX-7 port) and the resulting count is passed explicitly +(`library_config.sm_model_rdma_gbs`). Elsewhere the count is left to DeepEP, as vLLM leaves it. With overlap off the model's own 10-26 SMs are raised to 64 either way. **A virtualized pool can make a scale-out row measure the hypervisor rather than the fabric.** h200-dgxc EP16 on deepep-v2 paid three to eight times h100's cross-node cost while nccl-ep on the @@ -929,7 +930,7 @@ One raw case document, committed at `results//.json`, carries `rec library resolved that changes what a row measures, null where an adapter records none. deepep-v2 records `engine_contract` (`vllm`) in both modes and, in `normal`, its SM and QP counts, allocated QPs, LSA team, hybrid choice, vLLM's buffer flags, host-sync, expand and receive sizing - (`sm_model_rdma_gbs` on EFA only); the shared low-latency path, on deepep-v2 and uccl-ep alike, + (`sm_model_rdma_gbs` where the registry sets `rdma_gbs`); the shared low-latency path, on deepep-v2 and uccl-ep alike, records `receive_capacity`, `num_qps_per_rank`, `return_recv_hook`, `zero_copy` and `fp8_scales`, plus deepep-v2's NVLink and MNNVL flags; uccl-ep adds its verified `deep_ep` identity, buffer bytes, QPs, `is_intranode` and running CPU-proxy threads, with `Buffer.num_sms` and the dispatch