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: InfiniBand vs Ethernet. En ConnectX med dobbelt tilstand vender med mlxconfig -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:

  1. 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.
  2. PFC på RDMA-prioriteten. Linklagspause, der forhindrer tab af en bestemt trafikklasse. Standardpraksis: RDMA på prioritet 3, alt andet på prioritet 0.
  3. 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:

  1. Virksomhedens netværk / WAN — modelregistre, datasætlagring (S3, NFS, MinIO), Git, containerregistre, telemetri.
  2. Udvikler-arbejdsstationer — ingeniører der SSH'er ind, starter job, kopierer checkpoints ud, kører Jupyter.
  3. 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

Dataplan
  • 100/200/400 GbE RoCE eller HDR/NDR InfiniBand
  • NCCL, datasætlæsninger, kontrolpunktskrivninger
  • Tabsfri, PFC/ECN, dedikerede switche
  • Steril — ingen ikke-AI-trafik
Ledelsesplan
  • 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:

  1. Tilslut ledninger og tjek først forbindelseslaget. Kør ibstat på hver node. Samme hastighed, samme MTU, samme linklag. Ret det fysiske lag, før du rører ved software.
  2. Installer MLNX_OFED, ikke bare rdma-core, Hvis GPUDirect eller NCCL er omfattet. Match OFED-buildet med den kørende kerne.
  3. Kør perftest mellem 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.
  4. Load nvidia-peermem, bevis det med ib_write_bw --use_cuda=0. Resultatet skal stemme overens med vært-hukommelsestilfældet.
  5. 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.
  6. Kør nccl-tests allreduce på 2 noder, derefter 4, og derefter 8. Undersøg NCCL_DEBUG=INFO output ved første kørsel af hver klyngestørrelse. Bekræft NET/IB ... GDR dukker op.
  7. Separate stoffer. Administration på billig 1/10 GbE. Data på RDMA-strukturen. Del ikke.
  8. 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.
  9. 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.