RDMA-opsætning i praksis + Cluster Uplink Design
De tidligere artikler i N-sporet argumenterede for RDMA (N02) og gennemgik topologivalg (N04, N05). Denne del er den praktiske del: installer driverne, bevis at stien virker, tænd GPUDirect, valider NCCL, gå derefter et skridt op og tænk over, hvordan hele klyngen forbinder sig til verden.
Vi antager Ubuntu 22.04 eller 24.04, Mellanox/NVIDIA ConnectX-5 eller ConnectX-6 NIC'er, og enten InfiniBand HDR/NDR eller RoCEv2 over et tabsfrit Ethernet-netværk. Kommandoerne er dem, vi rent faktisk skriver på Kentino-testbænke, før en 4-node K-AI-klynge sendes.
Drivere: MLNX_OFED eller upstream rdma-core?
| Sti | Hvad får du | Hvornår skal man vælge det |
|---|---|---|
| MLNX_OFED (nu NVIDIA DOCA-OFED) | NVIDIA-testet driverpakke, GPUDirect peermem, perftest, mlxconfig | Produktions-AI-klynger med ConnectX-6/7 og GPUDirect |
opstrøms rdma-core + i træet mlx5
|
Hvad Ubuntu leverer, intet ekstra repository | Labbokse, enkeltnode, ingen GPUDirect, ingen firmwareværktøjer |
For alt, der transporterer NCCL-trafik i produktion, skal du installere MLNX_OFED. Upstream-systemet mlx5 virker, men du taber mlxconfig, den bundtede perftest, og — vigtigst af alt — en kerneside nvidia-peermem testet mod det samme OFED-træ.
En ren installation på Ubuntu 22.04 med kernel 5.15.x:
tar xf MLNX_OFED_LINUX-*.tgz && cd MLNX_OFED_LINUX-*
sudo ./mlnxofedinstall --add-kernel-support --with-nvmf --force
sudo /etc/init.d/openibd restart && sudo systemctl enable openibd
--add-kernel-support flag betyder noget. Spring det over på en kerne uden for OFED-matricen, og DKMS-buildet fejler lydløst — du ender med at køre standard mlx5 uden at vide det. Bekræft brugerpladsstakken med dpkg -l | grep -E 'libibverbs|rdma-core|mlnx-ofed'.
Hent linket frem, og bekræft at netværkskortet ser stoffet.
Tre kommandoer fortæller dig alt det vigtige:
sudo mst start && mst status # firmware tools
ibstat # port state, width, speed
ibv_devinfo -v # GIDs, max_qp, MTU, hw revision
En sund havn viser State: Active, Physical state: LinkUp, den forventede Rate: (f.eks. 200), og højre Link layer: (InfiniBand eller Ethernet). De to felter, folk overser:
-
Link layer: InfiniBandvsEthernet. En ConnectX med dobbelt tilstand vender medmlxconfig -d /dev/mst/mt4125_pciconf0 set LINK_TYPE_P1=2(1=IB, 2=Ethernet). Genstart påkrævet. -
Rate:matcher forventet hastighed. En 200 Gb/s NDR-port, der kom op ved 100 Gb/s, er den mest almindelige lydløse fejl: dårligt kabel, forkert DAC-længde eller switchport tvungen lav. Tjek før benchmarking.
På RoCE skal du også bekræfte, at v2 er valgt (v1 er ethertype 0x8915, v2 er UDP/4791 og er det, som alle moderne stak bruger): sudo cma_roce_mode -d mlx5_0 -p 1 -m 2.
Subnet-manager (kun InfiniBand)
InfiniBand er ikke Ethernet — intet på fabric-strukturen routerer, før en subnet manager (SM) tildeler LID'er. På en lab-fabric, sudo apt install opensm && sudo systemctl enable --now opensm på én node. I produktion, kør den integrerede SM på switchen. To software-SM'er, der kører om kap med hinanden, er en eftermiddag med debugging, som ingen har brug for. RoCE har ingen SM — routing er Ethernet-strukturens opgave, hvilket er grunden til, at RoCE-konfiguration primært handler om switch QoS, ikke om værten.
Bevis at RDMA rent faktisk virker: perftest
Før enhver NCCL- eller framework-kørsel, skal ledningen bevises med perftestTo noder, server først:
# server (node A) # client (node B)
ib_send_bw -d mlx5_0 -F --report_gbits -D 10
ib_send_bw -d mlx5_0 -F --report_gbits -D 10 10.10.1.1
Forventede tal på et rent stof:
| Link |
ib_send_bw (stor besked) |
ib_send_lat (2-byte) |
|---|---|---|
| 100 Gb/s EDR / 100 GbE RoCE | 95–98 Gb/s | 1.0–1.5 µs |
| 200 Gb/s HDR / 200 GbE RoCE | 188–197 Gb/s | 0.9–1.3 µs |
| 400 Gb/s NDR | 370–395 Gb/s | 0.8–1.1 µs |
Hvis du er 20% under disse tal, så begynd ikke at jagte NCCL-tuning. Strukturen er forkert. Tjek i rækkefølge: (1) MTU, (2) PFC på RoCE, (3) kabel/transceiver-parret, (4) PCIe-generering og -baneantal for NIC'en, (5) NUMA-placering. Latens på under en mikrosekund er opnåelig for in-rack NDR; alt over 5 µs på en single-switch RoCE-struktur er defekt.
GPUDirect RDMA: aktivering af DMA-stien
Hele pointen med RDMA i en AI-klynge er, at NIC'en læser og skriver GPU-hukommelse direkte og omgår værten. Det kræver nvidia-peermem (eller, på nyere kerner, DMA-BUF — NVIDIA anbefaler nu DMA-BUF, hvor kernen understøtter det, men de fleste produktionsstakke leverer stadig peermem).
sudo modprobe nvidia-peermem
lsmod | grep nvidia_peermem
echo nvidia-peermem | sudo tee /etc/modules-load.d/nvidia-peermem.conf
Hvis den ikke indlæses, blev kernen ikke bygget mod en OFED-bevidst RDMA peer-hukommelses-API. Installationsrækkefølgen er vigtig: OFED først, derefter NVIDIA-driveren, og derefter nvidia-peermem — peermem bygger mod OFED-headerne på installationstidspunktet.
Bevis end-to-end-stien med en GPU-til-GPU RDMA-skrivning:
# server # client
ib_write_bw -d mlx5_0 --use_cuda=0 -F --report_gbits -D 10
ib_write_bw -d mlx5_0 --use_cuda=0 -F --report_gbits -D 10 10.10.1.1
--use_cuda=0 registrerer CUDA-hukommelse på GPU 0 som RDMA-buffer. Hvis resultatet er inden for et par procent af vært-hukommelsestilfældet, fungerer GPUDirect. Hvis det er 5 gange langsommere, kører stien gennem værtshukommelsen — normalt et peermem-belastningsproblem eller en PCIe-topologi, hvor NIC og GPU sidder på modsatte NUMA-noder.
MTU og PFC for RoCE (det er her, RoCE-klynger lever eller dør)
RoCEv2 over et tabsfrit Ethernet-stof kræver tre ting, der fungerer sammen:
- En stor MTU end-to-end. Indstil 9000 på hvert NIC, switchport og routerhop. RoCE vælger den største IB-lignende MTU, der passer ind i Ethernet-MTU'en — 9000 Ethernet giver RoCE en 4096-byte MTU, hvilket er det, du ønsker.
- PFC på RDMA-prioriteten. Linklagspause, der forhindrer tab af en bestemt trafikklasse. Standardpraksis: RDMA på prioritet 3, alt andet på prioritet 0.
- ECN-mærkning på switche og NIC'er. ECN er det langsigtede signal for overbelastning; PFC er den kortsigtede nødbremse. ECN udfører arbejdet det meste af tiden; PFC aktiveres kun, når ECN ikke kan følge med.
På værtssiden, med mlnx_qos:
sudo mlnx_qos -i enp1s0f0 --pfc 0,0,0,1,0,0,0,0 # PFC on prio 3
sudo mlnx_qos -i enp1s0f0 --trust dscp
echo 106 | sudo tee /sys/class/infiniband/mlx5_0/tc/1/traffic_class
DSCP-værdien (26) og PFC-prioriteten (3) skal stemme overens ved hvert hop. Switchstrukturen skal afspejle dette: PFC aktiveret på prioritet 3, ECN-markering på disse køer, tabsfri bufferkonfiguration og headroom pr. port dimensioneret til BDP'en for det længste link.
At købe en switch fra en leverandør med dokumenterede RoCE-skabeloner (NVIDIA Spectrum, Arista, Cisco Nexus 9000) sparer en uge. Det er muligt at rulle PFC-konfigurationen manuelt på en generisk Broadcom-whitebox, men det er et projekt. Vi har gjort det. Vi anbefaler det ikke.
DCQCN (Data Center Quantized Congestion Notification) er kontrolløkken, der forbinder PFC og ECN: ECN markerer pakker, når en kø er fyldt, modtageren sender et ekko af en CNP tilbage, afsenderen sænker farten og øger derefter farten, når køen er tømt. PFC er fallback-funktionen, når DCQCN ikke kan reagere hurtigt nok. På moderne ConnectX-6/7 firmware er den aktiveret som standard, og ved 4-16 noder er standardindstillingerne fine. Justeringsspillet (alfa, målhastighed, byte/timer-tærskler) er for folk, der kører på skalaer, hvor 0.5% på allreduce er to ugers arbejde værd.
NCCL: de variabler, der betyder noget
NCCL er laget, der bruger RDMA til PyTorch, JAX, DeepSpeed, vLLM tensor-parallel og lignende. Det registrerer automatisk, for det meste korrekt. Fire miljøvariabler vises i hvert produktionsstartscript:
| Variabel | Hvad gør den | Hvornår skal den indstilles |
|---|---|---|
NCCL_IB_DISABLE |
1 tvinger TCP-sockets frem i stedet for IB/RoCE |
Kun fejlretning |
NCCL_SOCKET_IFNAME |
Grænseflade til NCCL bootstrap (ikke datastien) | Altid — peg på administrations-NIC'en, så bootstrap ikke kører over på RDMA-strukturen |
NCCL_IB_HCA |
Hvilke HCA('er) bruger NCCL til dataplanet | Multi-NIC-noder — eksplicit slår automatisk |
NCCL_NET_GDR_LEVEL |
Hvor aggressivt skal man bruge GPUDirect RDMA baseret på PCIe-topologi |
PIX/PHB når GPU'er og NIC'er deler en PCIe-switch / NUMA-node |
En fungerende opstart på en klynge med 4 noder og 4 GPU'er pr. node:
export NCCL_SOCKET_IFNAME=eno1 # 1 GbE management network
export NCCL_IB_HCA=mlx5_0,mlx5_1 # both RDMA NICs
export NCCL_IB_GID_INDEX=3 # RoCE v2 GID
export NCCL_NET_GDR_LEVEL=PHB
export NCCL_DEBUG=INFO # one-shot, then drop to WARN
mpirun -np 16 -N 4 --hostfile hosts -x NCCL_SOCKET_IFNAME \
-x NCCL_IB_HCA -x NCCL_IB_GID_INDEX -x NCCL_NET_GDR_LEVEL \
-x NCCL_DEBUG ./build/all_reduce_perf -b 8 -e 8G -f 2 -g 1
NCCL_DEBUG=INFO Outputtet er obligatorisk aflæsning ved første kørsel. Det fortæller dig, hvilken transport NCCL har valgt (Channel ... via NET/IB/0 GDR) pr. rang, pr. kanal. Se via NET/Socket hvor som helst, og RDMA-stien ikke bruges — du har ikke testet det, du tror, du har testet.
Validerer med nccl-tests
nccl-tests validerer hele stakken — driver, OFED, peermem, NCCL, netværk — end-to-end. Det tal, der betyder noget, er busbåndbredde (busbw), ikke algoritmebåndbredde (algbwBusbåndbredden normaliseres for ring-/træstørrelse og er den, du sammenligner med netværkskortets ledningshastighed.
| Klyngestørrelse | Forventet allreduce busbw (stor besked) |
|---|---|
| 1 node, 4 GPU'er over NVLink | 200–400 GB/s |
| 1 node, 8 GPU'er over NVLink | 250–500 GB/s |
| 2 noder, 4 GPU'er hver, 200 GbE RDMA | 20–24 GB/s |
| 4 noder, 4 GPU'er hver, 200 GbE RDMA + GDR | 20–22 GB/s |
Inter-node allreduce-grænser ved omtrent NIC-linjehastighed / 2 (allreduce sender og modtager hver byte én gang pr. rang). 200 Gb/s ≈ 25 GB/s loft; 22 GB/s observeret er sundt. Hvis tallet falder med 5 gange fra 1 til 2 noder, bruges RDMA ikke til intern-node-hop. Læs NCCL_DEBUG=INFO udgang.
Zoom nu ud: klynge uplink design
Alt ovenstående handler om dataplan — fabric-GPU'erne bruger til at kommunikere med hinanden. Den anden halvdel af en nyttig klynge er uplinkHvordan dette stof forbinder sig med omverdenen. Folk bygger hele tiden den forkerte uplink.
En K-AI-træningsklynge med 4 noder har tre eksterne relationer:
- Virksomhedens netværk / WAN — modelregistre, datasætlagring (S3, NFS, MinIO), Git, containerregistre, telemetri.
- Udvikler-arbejdsstationer — ingeniører der SSH'er ind, starter job, kopierer checkpoints ud, kører Jupyter.
- Andre klynger — en anden træningsklynge, en inferensklynge, en CI/eval-klynge.
Båndbreddematematik
Hvis 4 noder reducerer med ~22 GB/s hver, så interne Stoffet bevæger cirka 700 Gb/s øst-vest-tilslag. uplink behøver ikke at matche det. Det skal matche dataindtagelseshastighed:
- 4 noder × 4 GPU'er × ~1 GB/s pr. GPU (billed-/videomodel) = 16 GB/s ≈ 128 Gb/s vedvarende læsning fra objektlager.
- LLM-fortræning på tokeniseret tekst er langt mindre – 1–4 Gb/s, fordi tokens er tætte, og én batch holder længe.
- Finjusterede genladningscheckpoints topper ofte på 40 Gb/s i et par sekunder og falder derefter til næsten nul.
| arbejdsbyrde | Vedvarende indtagelse | Burst | Uplink |
|---|---|---|---|
| LLM-foruddannelse (tokeniseret tekst) | 1–4 Gb/s | 20 Gb / s | 25 GbE |
| Træning af billed-/videomodeller | 50–150 Gb/s | 200 Gb / s | 2× 100 GbE LAG eller 1× 200 GbE |
| Finjustering / RLHF med checkpoint shuffle | 5–20 Gb/s | 50 Gb / s | 25–100 GbE |
| Inferensklynge bag en load balancer | 5–50 Gb/s | modelafhængig | 25–100 GbE |
Almindelig fejl: at bruge €40 på en 400 GbE uplink, fordi den interne struktur er 400 GbE. Forkert mål. Det rigtige mål er datasættets læsehastighed. Vi har bygget 4-node klynger med en 25 GbE uplink, der kørte uden belastning i ugevis på LLM-tokendata.
Aggregeret vs. allokeret båndbredde
En node med fire 100 GbE NIC'er har 400 Gb/s samlet Ledningskapacitet. Denne kapacitet allokeres pr. flow, ikke samles. En enkelt TCP-forbindelse mellem to IP'er bruger ét NIC - højst 100 Gb/s. ECMP og hashing pr. flow distribueres forskellige flyder på tværs af de fire NIC'er.
-
Allreduce er mange parallelle flows — én pr. kanal pr. peer. NCCL spredes naturligt på tværs af flere NIC'er (
NCCL_IB_HCA(nævner begge). 4× 100 GbE er funktionelt tæt på 400 Gb/s for NCCL. - En enkelt datasætstrøm (én HTTP GET, der trækker en 1 TB shard) er ét flow. 4× 100 GbE giver det 100 Gb/s, ikke 400. For at bruge aggregatet skal dataloaderen åbne parallelle streams – hvilket DALI, WebDataset og MosaicMLs Streaming alle gør per design.
Stoffadskillelse
- 100/200/400 GbE RoCE eller HDR/NDR InfiniBand
- NCCL, datasætlæsninger, kontrolpunktskrivninger
- Tabsfri, PFC/ECN, dedikerede switche
- Steril — ingen ikke-AI-trafik
- 1 GbE eller 10 GbE
- SSH, Prometheus, NTP, syslog, IPMI/BMC
- Billige switche, standard L2/L3, ingen særlig QoS
- Virker altid, selv hvis datastrukturen er nede
Kør altid to strukturer. Administrationsplanet må ikke være afhængigt af dataplanet for at fungere – du skal have SSH-adgang, når RDMA-strukturen er brudt.
Administrationsplanet er ikke valgfrit. Når datastrukturen går i stykker — defekt transceiver, fejlkonfiguration af PFC, switchnedbrud — har du brug for en SSH-sti, der ikke afhænger af den ødelagte struktur. Fejlfinding af en RoCE-storm over det link, der stormer, er den slags fejl, man laver præcis én gang. IPMI/BMC og NTP findes også her; clock-skew er usynlig, indtil dit distribuerede framework begynder at producere forkerte gradienter.
BGP unummereret for rutede Clos
Over ~8 noder bliver L2 leaf-spine smertefuldt — spænder over trægrænser, skalering af MAC-tabel, broadcast storms, ingen native multi-path. Det moderne svar er en L3 routed Clos: hvert leaf-spine link er unummereret, BGP bærer ruter, ECMP spreder flows på tværs af spines.
Unummererede BGP-peers over IPv6 link-local adresserer kernens automatiske tildelinger, så du springer bogføringen per-link /31 helt over. Et leaf, der kører FRRouting på Linux, ser nogenlunde sådan ud:
router bgp 65001
neighbor swp1 interface remote-as external
neighbor swp2 interface remote-as external
address-family ipv4 unicast
network 10.1.1.0/24
redistribute connected
Hvert blad og hver spine er sit eget AS, eBGP reklamerer med loopbacks, ECMP på tværs af spines er gratis. RFC 7938 dokumenterer mønsteret; Cumulus/NVIDIA, Arista, Cisco og Juniper understøtter alle unummereret BGP i dag. Ved 4 noder er en enkelt switch fin. Ved 8-16 noder med to spines begynder routede Clos at betale for sig selv. Over 16 noder er det det eneste fornuftige svar.
Forbindelse til andre klynger
Placer ikke en træningsklynge og en inferensklynge på den samme RDMA-struktur. Træning er enorm bursty (allreduce); inferens er små beskeder i steady-state; QoS-kravene afviger; en træningskørsel med dårlig opførsel vil udsulte inferensstien. To separate strukturer, der mødes på en L3-router med normal IP-routing, er det rigtige svar. Kontroltrafik på tværs af klynger - jobkøer, logforsendelse, artefaktoverførsel - kører på administrationsplanet eller et dedikeret Ethernet-link på tværs af klynger. En 70B-vægtfil er ~140 GB; et checkpoint er 2 gange så tungt. Ved 25 GbE tager det ~90 sekunder; ved 100 GbE, ~22 sekunder. Planlæg for den større ende.
Hvad skal jeg gøre næste
En rimelig arbejdsgang til at stille RDMA op på en frisk klynge:
-
Tilslut ledninger og tjek først forbindelseslaget. Kør
ibstatpå hver node. Samme hastighed, samme MTU, samme linklag. Ret det fysiske lag, før du rører ved software. -
Installer MLNX_OFED, ikke bare
rdma-core, Hvis GPUDirect eller NCCL er omfattet. Match OFED-buildet med den kørende kerne. -
Kør
perftestmellem hvert par af noder før man rører ved rammer. Tal inden for 5% af teoretisk værdi = sundt. Alt under = stop og ret. -
Load
nvidia-peermem, bevis det medib_write_bw --use_cuda=0. Resultatet skal stemme overens med vært-hukommelsestilfældet. - Konfigurer PFC, ECN og DCQCN hvis du er på RoCE. På IB findes dette trin ikke; det er halvdelen af grunden til, at folk vælger IB.
-
Kør
nccl-testsallreduce på 2 noder, derefter 4, og derefter 8. UndersøgNCCL_DEBUG=INFOoutput ved første kørsel af hver klyngestørrelse. BekræftNET/IB ... GDRdukker op. - Separate stoffer. Administration på billig 1/10 GbE. Data på RDMA-strukturen. Del ikke.
- Størrelsen på uplinket til dit datasæts indtagelseshastighed, ikke til den interne strukturhastighed. De fleste klynger har brug for langt mindre ekstern båndbredde, end de har.
- Over 8 noder, planlagt routing af Clos med BGP unummereret. Under 8 er en enkelt kontakt fint.
Opfølgende artikler i N-sporet dækker latenstidsdissektionen (N06) og routingkompleksiteten (N07) — det er her, DCQCN-tuning og ECMP-hashingpatologier findes. K-sporet fortsætter herfra med distribueret træning (K02), inferensklynger (K03) og lagring (K04) — som alle antager, at RDMA-stakken på denne side allerede fungerer.
Dette er en del af Kentino Wiki, en referenceserie om AI-beregning og de systemer, der forbinder den. Rettelser er velkomne på info@kentino.com.