Summary
aiter/ops/communication.py:78 (init_dist_env) unconditionally does:
ca_comm.buffer = ca_comm._pool["input"].tensor
But when CustomAllreduce builds its input pool with raw_cached=True, that buffer is a plain hipMalloc region with no backing torch.Tensor, so the tensor property raises by design (custom_all_reduce.py:447):
RuntimeError: Uncached IPCBuffer has no backing tensor; use .data_ptr
Net effect: the raw_cached (plain-hipMalloc, IPC-exportable) input pool cannot be used at all. Any configuration that selects it fails during distributed init.
That matters because raw_cached is the path that keeps the pool exportable via hipIpcGetMemHandle, and it is currently the only mitigation for co-resident engines — see Impact.
Reproduction
8× MI350X (gfx950, SR-IOV VF), ROCm 7.2, rocm/atom-dev:nightly_202608191459 (bundled AITER 4fa508ef), GLM-5.2-MXFP4, one TP4 engine:
RuntimeError: Uncached IPCBuffer has no backing tensor; use .data_ptr
File "/app/aiter-test/aiter/ops/communication.py", line 78, in init_dist_env
ca_comm.buffer = ca_comm._pool["input"].tensor
File "/app/aiter-test/aiter/dist/device_communicators/custom_all_reduce.py", line 447, in tensor
File "/app/ATOM/atom/model_engine/model_runner.py", line 941, in _setup_device_and_distributed
raw_cached is gated at custom_all_reduce.py:1062:
raw_cached = _expandable_segments_enabled()
so it is reached two ways, and both fail identically:
PYTORCH_HIP_ALLOC_CONF=expandable_segments:True — the supported trigger.
- A one-line local patch adding an explicit override (
... or _env_flag("AITER_CAR_RAW_CACHED")).
Controls run to exclude our own environment:
| configuration |
result |
patched file mounted, override off (raw_cached=False) |
server READY — so the patch itself is harmless |
| override on, with our unrelated local AITER patches mounted |
dies |
| override on, pristine container (no other patches) |
dies — same traceback |
So this is not caused by anything we mount, and it is not a version skew: the only custom_all_reduce* change between fc2e5d57 (v0.1.20) and 4fa508ef is @compile_ops(..., develop=True) on three fused_allreduce_mhc_* stubs.
Impact
On this VF hardware, running two TP4 engines on one 8-GPU node fails at the default envelope:
custom_all_reduce.cu:417 fail to call hipIpcGetMemHandle(...) ---> [HIP error](invalid argument)
The first engine starts; the second cannot export its handle. Consistent with the torch.empty pool returning a caching-allocator pointer that is not IPC-exportable — exactly what raw_cached exists to avoid, and what #4174 / #4621 address for expandable segments.
Because raw_cached is unusable, the only working mitigation we found is to buy allocator headroom:
--gpu-memory-utilization / --max-num-seqs |
two engines? |
| 0.78 / 256 |
no |
| 0.70 / 128 |
no |
| 0.62 / 256 |
no |
| 0.62 / 128 |
yes |
Both dimensions must drop together. That costs real KV cache and half the sequence slots. Measured node throughput at 0.62/128 is 8465 tok/s aggregate; the alternative (guarding the second engine with NCCL_P2P_DISABLE=1 + AITER_DISABLE_IPC_COLLECTIVES=1) drops that engine's own end-to-end throughput by ~50% and yields 6440 aggregate.
Suggested fix
init_dist_env should use the pointer rather than the tensor, since IPCBuffer already exposes data_ptr for exactly this case — e.g. keep .tensor only where a tensor is genuinely required, or have init_dist_env branch on uncached/raw_cached. Happy to send a PR if you confirm the intended contract for ca_comm.buffer (tensor vs raw pointer) — it is consumed downstream and I did not want to guess.
Separately, it would help operationally if raw_cached were selectable on its own (e.g. AITER_CAR_RAW_CACHED=1) rather than only as a side effect of expandable_segments: co-resident deployments need the exportable pool but do not necessarily want expandable segments, which independently prevents this engine from starting.
Environment
- 8× MI350X (gfx950) SR-IOV VF, ROCm 7.2, TP4 per engine
rocm/atom-dev:nightly_202608191459, bundled AITER 4fa508ef2935110ff99adf2743ea93807dbd9c67
- Model GLM-5.2-MXFP4,
--level 3 --method mtp --num-speculative-tokens 3
PYTORCH_HIP_ALLOC_CONF unset unless stated
Summary
aiter/ops/communication.py:78(init_dist_env) unconditionally does:But when
CustomAllreducebuilds its input pool withraw_cached=True, that buffer is a plainhipMallocregion with no backingtorch.Tensor, so thetensorproperty raises by design (custom_all_reduce.py:447):Net effect: the
raw_cached(plain-hipMalloc, IPC-exportable) input pool cannot be used at all. Any configuration that selects it fails during distributed init.That matters because
raw_cachedis the path that keeps the pool exportable viahipIpcGetMemHandle, and it is currently the only mitigation for co-resident engines — see Impact.Reproduction
8× MI350X (gfx950, SR-IOV VF), ROCm 7.2,
rocm/atom-dev:nightly_202608191459(bundled AITER4fa508ef), GLM-5.2-MXFP4, one TP4 engine:raw_cachedis gated atcustom_all_reduce.py:1062:so it is reached two ways, and both fail identically:
PYTORCH_HIP_ALLOC_CONF=expandable_segments:True— the supported trigger.... or _env_flag("AITER_CAR_RAW_CACHED")).Controls run to exclude our own environment:
raw_cached=False)So this is not caused by anything we mount, and it is not a version skew: the only
custom_all_reduce*change betweenfc2e5d57(v0.1.20) and4fa508efis@compile_ops(..., develop=True)on threefused_allreduce_mhc_*stubs.Impact
On this VF hardware, running two TP4 engines on one 8-GPU node fails at the default envelope:
The first engine starts; the second cannot export its handle. Consistent with the
torch.emptypool returning a caching-allocator pointer that is not IPC-exportable — exactly whatraw_cachedexists to avoid, and what #4174 / #4621 address for expandable segments.Because
raw_cachedis unusable, the only working mitigation we found is to buy allocator headroom:--gpu-memory-utilization/--max-num-seqsBoth dimensions must drop together. That costs real KV cache and half the sequence slots. Measured node throughput at 0.62/128 is 8465 tok/s aggregate; the alternative (guarding the second engine with
NCCL_P2P_DISABLE=1+AITER_DISABLE_IPC_COLLECTIVES=1) drops that engine's own end-to-end throughput by ~50% and yields 6440 aggregate.Suggested fix
init_dist_envshould use the pointer rather than the tensor, sinceIPCBufferalready exposesdata_ptrfor exactly this case — e.g. keep.tensoronly where a tensor is genuinely required, or haveinit_dist_envbranch onuncached/raw_cached. Happy to send a PR if you confirm the intended contract forca_comm.buffer(tensor vs raw pointer) — it is consumed downstream and I did not want to guess.Separately, it would help operationally if
raw_cachedwere selectable on its own (e.g.AITER_CAR_RAW_CACHED=1) rather than only as a side effect ofexpandable_segments: co-resident deployments need the exportable pool but do not necessarily want expandable segments, which independently prevents this engine from starting.Environment
rocm/atom-dev:nightly_202608191459, bundled AITER4fa508ef2935110ff99adf2743ea93807dbd9c67--level 3 --method mtp --num-speculative-tokens 3PYTORCH_HIP_ALLOC_CONFunset unless stated