Skip to content

Commit d0ea82a

Browse files
committed
docs: address fabric-attachment review round
Eight of the ten findings; the other two are answered on their threads. The AKS section required IPC_LOCK and dshm but never said the training image must carry the IB verbs stack, though the EFA section says exactly that about libfabric. NCCL's IB transport dlopens rdma-core at runtime, so an image without it falls back to sockets and the job still passes. State the requirement. Other corrections: the linked Workload Pod Configuration section does not in fact document dshm, worker IPC_LOCK, daemon args or the NCCL settings, so stop claiming it does and point at the validator runtime for those; name nccl-env-profile.sh, since a runtime that attaches to FasTrak without sourcing it runs well under bandwidth; pin NCCL_SOCKET_IFNAME=eth0, which both tested runtimes set and which prevents a rendezvous hang on multi-NIC nodes; note that every shipped runtime defaults to NCCL_DEBUG=WARN, so the verification grep finds nothing on an ordinary run; describe the interfaces annotation as the nine-entry JSON array it is rather than eight bare names; quote the EFA placeholders, matching what buildEFAResourceLine emits. Drop the em dashes and slash from the three platform headings — per the repo's documentation style they render as double-hyphen anchors. Nothing links to them. Refs #2295 Signed-off-by: Yuan Chen <yuanchen97@gmail.com>
1 parent c4ff8fd commit d0ea82a

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

docs/user/fabric-attached-training.md

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,28 @@ That single limitation decides the rest:
3737
| EFA | EKS | no | your `TrainJob` |
3838
| InfiniBand / RDMA | AKS | no | your `TrainJob` |
3939

40-
## GKE GPUDirect TCPXO
40+
## GKE GPUDirect TCPXO
4141

4242
TCPXO needs the `tcpxo-daemon` sidecar, so the wiring cannot live in a TrainJob.
4343
`TrainingRuntime` is an ordinary namespaced resource: author one in your
4444
namespace and reference it from `runtimeRef`.
4545

46-
**What that runtime must carry**, all of it documented in
47-
[Workload Pod Configuration](../integrator/gke-tcpxo-networking.md#workload-pod-configuration-nri-profile):
46+
**What that runtime must carry.** The annotations and sidecar are specified in
47+
[Workload Pod Configuration](../integrator/gke-tcpxo-networking.md#workload-pod-configuration-nri-profile);
48+
the `dshm` volume, worker `IPC_LOCK`, daemon `args` and NCCL settings are not in
49+
that section — take them from AICR's validator runtime, cited below.
4850

4951
- the `networking.gke.io/interfaces` and `devices.gke.io/container.tcpxo-daemon`
5052
annotations, on the pod template metadata
5153
- the `tcpxo-daemon` native sidecar, at the version paired with the plugin your
5254
cluster runs
5355
- four hostPath volumes plus a memory-backed `dshm` at `/dev/shm`, and `IPC_LOCK`
5456
on the worker
55-
- the NCCL configuration for your plugin release
57+
- the NCCL configuration for your plugin release. The ~40 `NCCL_FASTRAK_*`
58+
tuning variables ship as `/usr/local/nvidia/lib64/nccl-env-profile.sh`, laid
59+
down by the plugin installer and version-matched to it. Source that file in
60+
your container's startup rather than transcribing the variables — a job that
61+
skips it still attaches to the fabric, but runs well under its bandwidth
5662

5763
**A placement sketch**`"<...>"` marks a value you must fill in. It shows
5864
where each piece goes; it is not a manifest, abridged or otherwise, and the
@@ -81,7 +87,7 @@ spec:
8187
annotations:
8288
devices.gke.io/container.tcpxo-daemon: "<NRI device list — see reference>"
8389
networking.gke.io/default-interface: eth0
84-
networking.gke.io/interfaces: "<YOUR 8 network names — see below>"
90+
networking.gke.io/interfaces: "<JSON array, 9 entries — see reference>"
8591
spec:
8692
nodeSelector: "<carry over from your bundle>"
8793
tolerations: "<carry over from your bundle>"
@@ -174,7 +180,7 @@ which prefers the TrainJob's value and can yield `PET_NPROC_PER_NODE=1`.
174180

175181
If you must set it, repeat *every* resource in it, including the GPU request.
176182

177-
## EKS EFA
183+
## EKS EFA
178184

179185
EFA needs no sidecar, so a TrainJob can attach to it against a generic runtime
180186
such as the `torch-distributed` runtime AICR ships. It needs three things:
@@ -196,10 +202,10 @@ spec:
196202
resourcesPerNode:
197203
limits:
198204
nvidia.com/gpu: 8
199-
vpc.amazonaws.com/efa: <EFA_COUNT> # per node — read it, see below
205+
vpc.amazonaws.com/efa: "<EFA_COUNT>" # per node — read it, see below
200206
requests:
201207
nvidia.com/gpu: 8
202-
vpc.amazonaws.com/efa: <EFA_COUNT>
208+
vpc.amazonaws.com/efa: "<EFA_COUNT>"
203209
```
204210

205211
**`IPC_LOCK` and `FI_EFA_FORK_SAFE=1`.** `torch-distributed` grants neither —
@@ -209,6 +215,11 @@ other `FI_*` variables in `spec.trainer.env`, and `IPC_LOCK` via a
209215
(`securityContext` is patchable there even though `env` is not). Without
210216
`IPC_LOCK`, NCCL may fail to register pinned buffers.
211217

218+
**`NCCL_SOCKET_IFNAME=eth0`.** AICR's tested EFA and InfiniBand runtimes both pin
219+
this so NCCL's bootstrap uses the control interface. On a multi-NIC node — p5
220+
carries several EFA ENIs — NCCL may otherwise pick a secondary, non-routable NIC
221+
for rendezvous and hang during initialization, before any transport is chosen.
222+
212223
**An image carrying the EFA stack.** AICR installs the device plugin, which
213224
exposes the devices — it does not put `libfabric` or `aws-ofi-nccl` into your
214225
training image. An ordinary PyTorch image will fall back to sockets no matter
@@ -226,7 +237,7 @@ kubectl get nodes -l <your-gpu-pool-selector> \
226237
-o custom-columns='NODE:.metadata.name,EFA:.status.allocatable.vpc\.amazonaws\.com/efa'
227238
```
228239

229-
## AKS InfiniBand / RDMA
240+
## AKS InfiniBand and RDMA
230241

231242
Also TrainJob-expressible. AICR fixes the resource name and the value is always
232243
`1`:
@@ -255,6 +266,12 @@ the device is allocated, which reads as an NCCL bug rather than a missing
255266
capability. Add it the same way as for EFA: a `runtimePatches` entry setting
256267
`securityContext` on the `node` container.
257268

269+
**An image carrying the IB verbs stack.** As with EFA, allocating the device is
270+
not enough: NCCL's IB transport dlopens `libibverbs` and the rest of rdma-core at
271+
runtime. An image without them logs `NET/IB : No device found` and falls back to
272+
sockets — the job still completes, just over TCP. Build from a base that carries
273+
rdma-core, or install it in the image.
274+
258275
**A memory-backed `/dev/shm` is also expected.** AICR's tested runtime mounts a
259276
`dshm` volume (`emptyDir: {medium: Memory}`) there; the default 64 MiB `/dev/shm`
260277
is small for multi-process NCCL.
@@ -264,7 +281,10 @@ prerequisites.
264281

265282
## Verifying the fabric is in use
266283

267-
Run a short job with `NCCL_DEBUG=INFO` and check which transport NCCL selected:
284+
Run a short job with `NCCL_DEBUG=INFO` and check which transport NCCL selected.
285+
Every runtime AICR ships sets `NCCL_DEBUG=WARN`, at which this line is
286+
suppressed — so grepping an ordinary run finds nothing, which is not evidence of
287+
socket fallback:
268288

269289
```shell
270290
kubectl logs <worker-pod> -c node | grep -i 'NCCL INFO.*Using network'

0 commit comments

Comments
 (0)