RDMA v praxi + návrh uplinků clusteru

Předchozí články v řadě N zdůvodnily nasazení RDMA (N02) a provedly vás volbou topologie (N04, N05). Tento díl je praktický: nainstalovat ovladače, ověřit, že cesta funguje, zapnout GPUDirect, validovat NCCL a poté se povznést o patro výš a promyslet, jak se celý cluster připojuje ke zbytku světa.

Předpokládáme Ubuntu 22.04 nebo 24.04, síťové karty Mellanox/NVIDIA ConnectX-5 nebo ConnectX-6 a buď InfiniBand HDR/NDR, nebo RoCEv2 nad bezeztrátovou ethernetovou sítí. Uvedené příkazy jsou přesně ty, které skutečně píšeme na testovacích stolicích Kentino, než od nás odejde čtyřuzlový cluster Kentino AI.

Ovladače: MLNX_OFED, nebo upstreamový rdma-core?

Varianta Co získáte Kdy ji zvolit
MLNX_OFED (nyní NVIDIA DOCA-OFED) Balík ovladačů otestovaný NVIDIÍ, GPUDirect peermem, perftest, mlxconfig Produkční AI clustery s ConnectX-6/7 a GPUDirect
Upstreamový rdma-core + in-tree mlx5 To, co dodává Ubuntu, bez dalšího repozitáře Laboratorní stroje, jeden uzel, bez GPUDirect, bez nástrojů pro firmware

Pro cokoli, co v produkci přenáší provoz NCCL, nainstalujte MLNX_OFED. Upstreamový mlx5 sice funguje, ale přijdete o mlxconfig, o přibalený perftest a — což je nejdůležitější — o modul nvidia-peermem na straně jádra otestovaný proti témuž stromu OFED.

Čistá instalace na Ubuntu 22.04 s jádrem 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

Přepínač --add-kernel-support je zásadní. Pokud jej na jádře mimo matici OFED vynecháte, sestavení DKMS tiše selže — a vy nakonec provozujete standardní mlx5 a nevíte o tom. Stav user-space stacku ověříte příkazem dpkg -l | grep -E 'libibverbs|rdma-core|mlnx-ofed'.

Nahoďte linku a ověřte, že karta vidí síť

Vše podstatné vám řeknou tři příkazy:

sudo mst start && mst status   # firmware tools
ibstat                          # port state, width, speed
ibv_devinfo -v                  # GIDs, max_qp, MTU, hw revision

Zdravý port hlásí State: Active, Physical state: LinkUp, očekávanou hodnotu Rate: (např. 200) a správnou Link layer: (InfiniBand, nebo Ethernet). Dvě pole, která se běžně přehlédnou:

  • Link layer: InfiniBand vs. Ethernet. Dvourežimovou kartu ConnectX přepnete příkazem mlxconfig -d /dev/mst/mt4125_pciconf0 set LINK_TYPE_P1=2 (1 = IB, 2 = Ethernet). Je nutný restart.
  • Rate: odpovídá očekávané rychlosti. Port NDR 200 Gb/s, který naběhl na 100 Gb/s, je nejčastější tichá závada: vadný kabel, nesprávná délka DAC nebo port switche natvrdo omezený na nižší rychlost. Zkontrolujte to dřív, než začnete měřit výkon.

U RoCE navíc ověřte, že je zvolena verze v2 (v1 má ethertype 0x8915, v2 běží na UDP/4791 a používá ji každý moderní stack): sudo cma_roce_mode -d mlx5_0 -p 1 -m 2.

Subnet manager (pouze InfiniBand)

InfiniBand není Ethernet — v síti se nic nesměruje, dokud subnet manager (SM) nepřidělí LID. V laboratorní síti stačí na jednom uzlu spustit sudo apt install opensm && sudo systemctl enable --now opensm. V produkci používejte vestavěný SM na switchi. Dva softwarové SM, které si navzájem konkurují, znamenají odpoledne ladění, které nikdo nepotřebuje. RoCE žádný SM nemá — směrování je úkolem ethernetové sítě, a proto se konfigurace RoCE točí hlavně kolem QoS na switchi, nikoli kolem hostitele.

Ověřte, že RDMA skutečně funguje: perftest

Ještě před jakýmkoli během NCCL nebo frameworku prověřte samotné vedení nástrojem perftest. Dva uzly, nejprve server:

# 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

Očekávané hodnoty na čisté síti:

Linka ib_send_bw (velké zprávy) ib_send_lat (2 bajty)
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

Jste-li o 20 % pod těmito hodnotami, nezačínejte ladit NCCL. Chyba je v síti. Kontrolujte v tomto pořadí: (1) MTU, (2) PFC u RoCE, (3) dvojici kabel/transceiver, (4) generaci PCIe a počet linek pro síťovou kartu, (5) umístění v rámci NUMA. Latence pod jednu mikrosekundu je u NDR v rámci racku dosažitelná; cokoli nad 5 µs na jednoswitchové síti RoCE je rozbité.

GPUDirect RDMA: zapnutí DMA cesty

Celý smysl RDMA v AI clusteru spočívá v tom, že síťová karta čte a zapisuje přímo do paměti GPU a obchází hostitele. K tomu je potřeba nvidia-peermem (nebo na novějších jádrech DMA-BUF — NVIDIA dnes doporučuje DMA-BUF tam, kde jej jádro podporuje, ale většina produkčních stacků stále dodává peermem).

sudo modprobe nvidia-peermem
lsmod | grep nvidia_peermem
echo nvidia-peermem | sudo tee /etc/modules-load.d/nvidia-peermem.conf

Pokud se modul nepodaří načíst, jádro nebylo sestaveno proti API pro RDMA peer memory se znalostí OFED. Záleží na pořadí instalace: nejprve OFED, pak ovladač NVIDIA a nakonec nvidia-peermem — peermem se při instalaci sestavuje proti hlavičkám OFED.

Celou cestu ověřte zápisem RDMA mezi dvěma GPU:

# 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 registruje paměť CUDA na GPU 0 jako RDMA buffer. Pokud se výsledek pohybuje v řádu jednotek procent od varianty s hostitelskou pamětí, GPUDirect funguje. Je-li 5× pomalejší, přenos se odehrává přes hostitelskou paměť — obvykle jde o problém s načtením peermem nebo o topologii PCIe, kde karta a GPU leží na opačných uzlech NUMA.

MTU a PFC pro RoCE (právě na tom clustery s RoCE stojí a padají)

RoCEv2 nad bezeztrátovou ethernetovou sítí vyžaduje souhru tří věcí:

  1. Velké MTU po celé trase. Nastavte 9000 na každé síťové kartě, portu switche i na každém směrovači. RoCE volí největší MTU ve stylu IB, které se vejde do ethernetového MTU — 9000 na Ethernetu dává RoCE MTU 4096 bajtů, a přesně to chcete.
  2. PFC na prioritě vyhrazené pro RDMA. Pozastavení na linkové vrstvě, které zabrání zahazování paketů ve vybrané třídě provozu. Běžná praxe: RDMA na prioritě 3, vše ostatní na prioritě 0.
  3. Značkování ECN na switchích a síťových kartách. ECN je dlouhodobý signál zahlcení, PFC krátkodobá záchranná brzda. Většinu práce odvede ECN; PFC se spustí jen tehdy, když ECN nestíhá.

Na straně hostitele pomocí 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

Hodnota DSCP (26) a priorita PFC (3) se musí shodovat na každém skoku. Síť switchů to musí zrcadlit: zapnuté PFC na prioritě 3, značkování ECN na těchto frontách, bezeztrátová konfigurace bufferů a rezerva na každém portu dimenzovaná na BDP nejdelší linky.

Nákup switche od výrobce s dokumentovanými šablonami pro RoCE (NVIDIA Spectrum, Arista, Cisco Nexus 9000) vám ušetří týden. Ruční konfigurace PFC na obecném whiteboxu s čipem Broadcom je proveditelná, ale je to samostatný projekt. Dělali jsme to. Nedoporučujeme to.

DCQCN (Data Center Quantized Congestion Notification) je regulační smyčka, která PFC a ECN spojuje: ECN označí pakety ve chvíli, kdy se plní fronta, příjemce odešle zpět CNP, odesílatel zpomalí a po vyprázdnění fronty opět zrychlí. PFC je záloha pro případ, že DCQCN nestihne zareagovat. Na moderním firmwaru ConnectX-6/7 je ve výchozím stavu zapnuté a při 4 až 16 uzlech výchozí hodnoty bohatě stačí. Ladění (alpha, cílová rychlost, prahy v bajtech a časovačích) je hrou pro ty, kdo provozují takové měřítko, kde 0,5 % u operace allreduce stojí za dva týdny práce.

NCCL: proměnné, na kterých záleží

NCCL je vrstva, která RDMA využívá pro PyTorch, JAX, DeepSpeed, tenzorově paralelní vLLM a podobné nástroje. Detekuje se automaticky, většinou správně. V každém produkčním spouštěcím skriptu se objeví čtyři proměnné prostředí:

Proměnná Co dělá Kdy ji nastavit
NCCL_IB_DISABLE 1 vynutí TCP sokety místo IB/RoCE Pouze při ladění
NCCL_SOCKET_IFNAME Rozhraní pro bootstrap NCCL (nikoli pro datovou cestu) Vždy — nasměrujte ji na management kartu, aby se bootstrap nepral o RDMA síť
NCCL_IB_HCA Které HCA používá NCCL pro datovou rovinu Uzly s více síťovými kartami — explicitní nastavení poráží automatiku
NCCL_NET_GDR_LEVEL Jak agresivně využívat GPUDirect RDMA podle topologie PCIe PIX/PHB tam, kde GPU a síťové karty sdílejí PCIe switch nebo uzel NUMA

Funkční spuštění na clusteru se čtyřmi uzly a čtyřmi GPU na uzel:

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

Výstup NCCL_DEBUG=INFO je při prvním běhu povinná četba. Řekne vám, jaký transport NCCL zvolilo (Channel ... via NET/IB/0 GDR) pro každý rank a každý kanál. Pokud se kdekoli objeví via NET/Socket, cesta přes RDMA se nepoužívá — netestovali jste to, co si myslíte.

Validace nástrojem nccl-tests

nccl-tests ověřují celý stack — ovladač, OFED, peermem, NCCL i síť — od začátku do konce. Číslo, na kterém záleží, je propustnost sběrnice (busbw), nikoli propustnost algoritmu (algbw). Propustnost sběrnice je normalizovaná na velikost kruhu či stromu a právě ji porovnáváte s rychlostí linky síťové karty.

Velikost clusteru Očekávaná busbw u allreduce (velké zprávy)
1 uzel, 4 GPU přes NVLink 200–400 GB/s
1 uzel, 8 GPU přes NVLink 250–500 GB/s
2 uzly, po 4 GPU, 200 GbE RDMA 20–24 GB/s
4 uzly, po 4 GPU, 200 GbE RDMA + GDR 20–22 GB/s

Allreduce mezi uzly je stropem omezen zhruba na polovinu linkové rychlosti karty (allreduce každý bajt jednou odešle a jednou přijme na každý rank). 200 Gb/s ≈ strop 25 GB/s; naměřených 22 GB/s je zdravá hodnota. Pokud hodnota při přechodu z jednoho uzlu na dva klesne 5×, pro přenos mezi uzly se RDMA nepoužívá. Přečtěte si výstup NCCL_DEBUG=INFO.

A teď o patro výš: návrh uplinku clusteru

Všechno výše se týká datové roviny — sítě, přes kterou spolu GPU komunikují. Druhou polovinou použitelného clusteru je uplink: způsob, jakým se tato síť připojuje k okolnímu světu. Špatně navržený uplink potkáváme neustále.

Čtyřuzlový tréninkový cluster Kentino AI má tři vazby na okolí:

  1. Firemní síť / WAN — registry modelů, úložiště datasetů (S3, NFS, MinIO), Git, registry kontejnerů, telemetrie.
  2. Workstationy vývojářů — inženýři se připojují přes SSH, spouštějí úlohy, kopírují checkpointy ven, provozují Jupyter.
  3. Další clustery — druhý tréninkový cluster, inferenční cluster, cluster pro CI a evaluace.

Výpočet propustnosti

Pokud 4 uzly provádějí allreduce rychlostí zhruba 22 GB/s každý, přenese interní síť v souhrnu asi 700 Gb/s provozu mezi uzly. Samotný uplink tomu odpovídat nemusí. Musí odpovídat rychlosti načítání dat:

  • 4 uzly × 4 GPU × zhruba 1 GB/s na GPU (obrazový či video model) = 16 GB/s ≈ 128 Gb/s trvalého čtení z objektového úložiště.
  • Předtrénování LLM nad tokenizovaným textem je mnohem skromnější — 1–4 Gb/s, protože tokeny jsou husté a jedna dávka vydrží dlouho.
  • Doladění, které často znovu načítá checkpointy, vyskočí na pár sekund na 40 Gb/s a pak spadne téměř na nulu.
Workload Trvalé načítání Špička Uplink
Předtrénování LLM (tokenizovaný text) 1–4 Gb/s 20 Gb/s 25 GbE
Trénink obrazových a video modelů 50–150 Gb/s 200 Gb/s 2× 100 GbE v LAG nebo 1× 200 GbE
Doladění / RLHF s přehazováním checkpointů 5–20 Gb/s 50 Gb/s 25–100 GbE
Inferenční cluster za load balancerem 5–50 Gb/s závisí na modelu 25–100 GbE

Častá chyba: utratit 40 000 € za uplink 400 GbE jen proto, že interní síť má 400 GbE. Špatné měřítko. Správným měřítkem je rychlost čtení datasetu. Postavili jsme čtyřuzlové clustery s uplinkem 25 GbE, které týdny jely naplno na tokenizovaných datech pro LLM.

Souhrnná versus přidělená propustnost

Uzel se čtyřmi kartami 100 GbE má souhrnnou kapacitu linek 400 Gb/s. Tato kapacita se ale přiděluje po tocích, nesdílí se v jednom fondu. Jediné TCP spojení mezi dvěma IP adresami využije jednu kartu — tedy nejvýše 100 Gb/s. ECMP a hashování po tocích rozprostírají mezi čtyři karty různé toky.

  • Allreduce představuje mnoho paralelních toků — jeden na kanál a protistranu. NCCL je nativně rozkládá na více karet (NCCL_IB_HCA s oběma uvedenými). Pro NCCL se 4× 100 GbE prakticky blíží 400 Gb/s.
  • Jediný datový proud datasetu (jeden HTTP GET stahující 1TB shard) je jeden tok. 4× 100 GbE mu dá 100 Gb/s, nikoli 400. Aby se využil souhrn, musí dataloader otevřít paralelní proudy — což DALI, WebDataset i Streaming od MosaicML dělají už z principu.

Oddělení sítí

Datová rovina
  • 100/200/400 GbE RoCE nebo InfiniBand HDR/NDR
  • NCCL, čtení datasetů, zápisy checkpointů
  • Bezeztrátová, PFC/ECN, vyhrazené switche
  • Sterilní — žádný provoz mimo AI
Management rovina
  • 1 GbE nebo 10 GbE
  • SSH, Prometheus, NTP, syslog, IPMI/BMC
  • Levné switche, standardní L2/L3, žádné zvláštní QoS
  • Funguje vždy, i když datová síť leží

Provozujte vždy dvě sítě. Management rovina nesmí být ve své funkci závislá na datové rovině — přístup přes SSH potřebujete právě ve chvíli, kdy je RDMA síť rozbitá.

Management rovina není volitelná. Když datová síť selže — vadný transceiver, špatně nastavené PFC, pád switche — potřebujete cestu přes SSH, která na rozbité síti nezávisí. Ladit bouři v RoCE přes linku, která právě bouří, je chyba, kterou uděláte přesně jednou. Patří sem i IPMI/BMC a NTP; rozjetí hodin je neviditelné do chvíle, než váš distribuovaný framework začne počítat špatné gradienty.

BGP unnumbered pro směrovanou Clos topologii

Nad zhruba 8 uzly začíná být leaf-spine na L2 bolestivý — limity spanning tree, škálování MAC tabulek, broadcastové bouře a žádné nativní multi-path. Moderní odpovědí je směrovaná Clos topologie na L3: každá linka leaf–spine je unnumbered, BGP nese trasy a ECMP rozprostírá toky přes spine prvky.

BGP unnumbered navazuje relace přes link-local adresy IPv6, které jádro přiděluje samo, takže evidenci sítí /31 pro každou linku zcela odpadá. Leaf s FRRouting na Linuxu vypadá zhruba takto:

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

Každý leaf i každý spine je vlastní AS, eBGP inzeruje loopbacky a ECMP přes spine prvky je zadarmo. Vzor popisuje RFC 7938; unnumbered BGP dnes podporují Cumulus/NVIDIA, Arista, Cisco i Juniper. U 4 uzlů stačí jediný switch. U 8 až 16 uzlů se dvěma spine prvky se směrovaná Clos topologie začíná vyplácet. Nad 16 uzlů je jedinou rozumnou odpovědí.

Propojení s dalšími clustery

Nedávejte tréninkový a inferenční cluster na tutéž RDMA síť. Trénink znamená obrovské nárazové operace allreduce, inference ustálený tok malých zpráv; požadavky na QoS se rozcházejí a nevydařený tréninkový běh inferenční cestu vyhladoví. Správnou odpovědí jsou dvě oddělené sítě, které se potkávají na L3 směrovači s běžným IP routingem. Řídicí provoz mezi clustery — fronty úloh, odesílání logů, přenos artefaktů — jede po management rovině nebo po vyhrazené ethernetové lince mezi clustery. Soubor s vahami modelu o 70B parametrech má zhruba 140 GB, checkpoint dvojnásobek. Při 25 GbE to trvá asi 90 sekund, při 100 GbE asi 22 sekund. Počítejte s tou větší variantou.

Co dělat dál

Rozumný postup při zprovoznění RDMA na novém clusteru:

  1. Nejprve vše zapojte a zkontrolujte linkovou vrstvu. Spusťte ibstat na každém uzlu. Stejná rychlost, stejné MTU, stejná linková vrstva. Fyzickou vrstvu dejte do pořádku dřív, než sáhnete na software.
  2. Nainstalujte MLNX_OFED, nejen rdma-core, pokud je ve hře GPUDirect nebo NCCL. Sestavení OFED musí odpovídat běžícímu jádru.
  3. Spusťte perftest mezi každou dvojicí uzlů ještě předtím, než sáhnete na frameworky. Hodnoty do 5 % od teoretického maxima = zdravý stav. Cokoli pod tím = zastavte a opravte.
  4. Načtěte nvidia-peermem a ověřte jej pomocí ib_write_bw --use_cuda=0. Výsledek by měl odpovídat variantě s hostitelskou pamětí.
  5. Nakonfigurujte PFC, ECN a DCQCN, pokud jste na RoCE. Na InfiniBandu tento krok vůbec neexistuje; to je polovina důvodu, proč lidé volí IB.
  6. Spusťte nccl-tests allreduce na 2 uzlech, pak na 4 a pak na 8. Při prvním běhu každé velikosti clusteru si projděte výstup NCCL_DEBUG=INFO. Ověřte, že se objeví NET/IB ... GDR.
  7. Oddělte sítě. Management na levném 1/10 GbE. Data na RDMA síti. Nesdílejte je.
  8. Uplink dimenzujte podle rychlosti načítání datasetu, nikoli podle rychlosti interní sítě. Většina clusterů potřebuje podstatně méně externí propustnosti, než má.
  9. Nad 8 uzlů plánujte směrovanou Clos topologii s BGP unnumbered. Pod 8 uzly stačí jediný switch.

Navazující články v řadě N rozebírají latenci (N06) a složitost směrování (N07) — právě tam najdete ladění DCQCN a patologie hashování v ECMP. Řada K navazuje distribuovaným tréninkem (K02), inferenčními clustery (K03) a úložišti (K04) — a všechny předpokládají, že RDMA stack popsaný na této stránce už funguje.


Toto je součást Kentino Wiki, referenční série o výpočetním výkonu pro AI a o systémech, které jej propojují. Opravy uvítáme na info@kentino.com.