Złożoność routingu w sieciach AI: ECMP, routing adaptacyjny, DCQCN i dlaczego środowisko HPC ma na tym punkcie obsesję
Wcześniejsze artykuły omówiły kable, karty NIC, przełączniki i topologie. Ten dotyczy tego, co dzieje się piętro wyżej: w jaki sposób pakiety znajdują drogę przez strukturę wielu przełączników i co powstrzymuje tę strukturę przed załamaniem, gdy dziesięć tysięcy GPU postanowi wykonać all-reduce w tej samej chwili.
Ruch AI wygląda zupełnie inaczej niż ruch w zwykłym centrum danych. Frontend webowy wysyła miliony drobnych połączeń TCP. Trenowanie AI wysyła kilka ogromnych, idealnie zsynchronizowanych strumieni do znanych odbiorców, a wszyscy czekają na najwolniejszy z nich. Techniki, które sprawdzają się w pierwszym przypadku, w drugim się rozsypują.
Zastrzeżenie na wstępie: większość klientów Kentino pracuje na klastrach 1–4 węzłów. W tej skali żaden z opisanych problemów realnie nie boli. Wystarczy połączyć cztery węzły jednym przełącznikiem 100 GbE (albo bez przełącznika — patrz N05), uruchomić zwykłe RoCE na ustawieniach domyślnych i nigdy nie myśleć o ECMP ani DCQCN. Piszemy o tym mimo wszystko, ponieważ (a) to przydatne tło przy decyzjach o wymiarowaniu oraz (b) w dniu, w którym z czterech węzłów robi się szesnaście, wszystko to nagle zaczyna mieć znaczenie.
Czym jest ECMP i dlaczego wystarczało do czasu AI
ECMP — Equal-Cost Multi-Path — to sztuczka routingowa, dzięki której działają struktury leaf-spine i fat-tree. Gdy z leafa A do leafa B prowadzi kilka ścieżek o równym koszcie (przez spine'y S1..S4), przełącznik haszuje pola pakietu i na podstawie hasza wybiera spine. Klasyczny hasz z pięciu pól to (src IP, dst IP, src port, dst port, protocol).
Dla tradycyjnych obciążeń chmurowych — milionów krótkotrwałych połączeń TCP — ECMP sprawdza się znakomicie. Prawo wielkich liczb samo wykonuje równoważenie obciążenia. Przy 10 000 strumieni i 8 spine'ach uzyskuje się wynik odbiegający od idealnego balansu o kilka procent.
- Ponad 10 000 krótkotrwałych strumieni TCP
- Prawo wielkich liczb równoważy spine'y
- Rozkład obciążenia niemal idealny
- Kolizja hasza ECMP: rzadka
- 8 strumieni-słoni, wszystkie naraz
- Hasz z pięciu pól kieruje wiele strumieni na ten sam spine
- Gorący spine = all-reduce o połowę wolniejszy
- Prawdopodobieństwo kolizji: ~97% przy 8 strumieniach na 8 spine'ach
ECMP zaprojektowano dla wielu małych strumieni. Trenowanie AI wysyła kilka ogromnych, zsynchronizowanych strumieni — równowaga statystyczna przestaje działać.
Problem strumieni-słoni
Trenowanie AI to przeciwieństwo ruchu webowego. Krok trenowania: każde GPU liczy gradient, każde GPU wysyła swój gradient do wszystkich pozostałych (allreduce), wszyscy czekają na najwolniejszy transfer, powtórka.
Allreduce to niewielka liczba bardzo dużych strumieni. Ring-allreduce na 8 węzłach z kartami 200 Gbps to 8 równoczesnych strumieni, każdy wielkości kilku gigabajtów, wszystkie z prędkością łącza, wszystkie startujące w tej samej chwili. Dokument Meta o RoCE w dużej skali opisał to jasno: w klastrach AI znikoma liczba strumieni-„słoni” odpowiada za niemal wszystkie bajty i wszystkie chcą sieci w tym samym momencie.
Hasz ECMP z pięciu pól tego nie znosi. Przy N strumieniach-słoniach na S ścieżkach prawdopodobieństwo braku kolizji wynosi S! / ((S-N)! · S^N). Dla 8 strumieni na 8 spine'ach: około 2.4%. Nawet 32 spine'y dla 8 strumieni dają zaledwie ~33%. Dokładanie spine'ów nie zmienia tego rzutu monetą — daje więcej pustych łączy, podczas gdy dwa strumienie biją się o jedno.
Kolizja przeciąża łącze spine w stosunku 2:1, dotknięte strumienie pracują o połowę wolniej, a ponieważ krok czeka na najwolniejszy strumień, cała iteracja zwalnia o połowę. Pomiary na klastrach produkcyjnych raportują, że kolizje ECMP powodują nawet 40% straty wydajności przy allreduce.
Obejścia: lepsze haszowanie, równoważenie na poziomie pakietów, routing adaptacyjny
Cztery realne odpowiedzi, w kolejności rosnącej trudności wdrożenia:
1. Lepsze haszowanie (E-ECMP, świadome QP). Najtańsze rozwiązanie. Standardowy hasz z pięciu pól sprowadza ruch RDMA do jednej krotki na parę QP — pojedynczy strumień allreduce to naprawdę jeden kubełek ECMP. Wystarczy haszować także numer docelowego QP RoCE i sprawić, by aplikacja rozkładała ruch na wiele QP („skalowanie QP”). Liczby Meta: do 40% lepszy allreduce. Nadal statystycznie — kolizje są rzadsze, nie wyeliminowane.
2. Przełączanie flowletów. Wykrycie przerwy w ruchu i ponowne haszowanie od tego miejsca. Działa dla TCP, słabo dla RoCE nadawanego bez przerw.
3. Równoważenie na poziomie pakietów / rozpraszanie pakietów. Haszowanie per pakiet, zgoda na zmianę kolejności, a karta NIC składa całość z powrotem. Eliminuje problem strumieni-słoni, ale wymaga współpracy karty i przełącznika. Tak właśnie działa NVIDIA Spectrum-X — rozpraszanie per pakiet ze sprzętowym porządkowaniem w SuperNIC.
4. Routing adaptacyjny. Przełącznik śledzi przeciążenie na każdym porcie i w momencie przełączania wybiera najmniej obciążoną ścieżkę o równym koszcie, zamiast haszować na ślepo. W połączeniu z rozpraszaniem pakietów to właśnie to, co InfiniBand ma od piętnastu lat. Przeniesienie tego do Ethernetu jest sztandarową funkcją rozwiązań NVIDIA Spectrum-X (układy Spectrum-4/5 plus karty BlueField lub ConnectX-8 SuperNIC), Cisco Silicon One G200/P200 oraz Broadcom Tomahawk 5 / Jericho 3-AI z komórkową strukturą ze szeregowaniem.
Dla klastrów 1–8 węzłów routing adaptacyjny to przesada. Dla zadań na 64+ GPU skalowanych do 1 000 GPU jest różnicą między „wąskim gardłem jest sieć” a „wąskim gardłem są GPU”. Dlatego każdy poważny dostawca Ethernetu dla AI zbudował lub licencjonował krzemu do routingu adaptacyjnego w latach 2024–2026.
Kontrola przeciążenia: dlaczego „po prostu nie gubmy pakietów” nie jest darmowe
Druga połowa złożoności routingu to pytanie, co się dzieje, gdy do jednego portu przełącznika trafia naraz zbyt dużo ruchu. Dwie możliwości: sieć stratna gubi pakiety, a punkty końcowe zwalniają (tak działa otwarty internet); sieć bezstratna wymusza na przełączniku powyżej wstrzymanie nadawania — bez strat, ale przeciążenie propaguje się wstecz.
RoCE historycznie wymagał struktury bezstratnej. Karty RDMA źle znoszą utratę pakietów — pojedynczy zgubiony pakiet wyzwala retransmisję go-back-N całej wiadomości, co przy 100 GbE oznacza ponowne wysłanie megabajtów. RoCEv2 z go-back-N jest w praktyce nie do użytku w sieci stratnej przy wysokim wykorzystaniu.
PFC — Priority Flow Control (IEEE 802.1Qbb) to mechanizm, dzięki któremu Ethernet zachowuje się bezstratnie. Gdy kolejka wyjściowa przełącznika dla danego priorytetu przekroczy próg, przełącznik wysyła w górę ramkę PAUSE z prośbą o wstrzymanie nadawania na tym priorytecie. Osiem priorytetów, osiem niezależnych sygnałów stop/start.
Blokowanie czoła kolejki i strumienie-ofiary
Pauzy PFC są zgrubne. Pauza mówi „przestań nadawać priorytet 3 na tym łączu” — nie wie, który strumień wywołał przeciążenie. Jeśli dziesięć strumieni dzieli priorytet 3, a jeden z nich jest przeciążony dalej w sieci, PFC wstrzymuje wszystkie dziesięć. Pozostałych dziewięć „strumieni-ofiar” zostaje ukaranych za cudzy problem. To jest blokowanie czoła kolejki, podstawowa bolączka bezstratnego Ethernetu w dużej skali.
Blokowanie czoła kolejki: A→X wywołuje PFC na łączu trunk. B i C rozmawiające z Y (u którego wszystko jest w porządku) też zostają wstrzymane — to strumienie-ofiary.
Zakleszczenie PFC: jeśli topologia i ruch utworzą cykliczną zależność wstrzymanych łączy — A czeka na B, B na C, C na A — cała struktura się blokuje. Obserwowane w środowiskach produkcyjnych. Nowoczesne przełączniki mają wykrywanie zakleszczeń, a nowoczesne topologie Clos są wolne od zakleszczeń z samej konstrukcji; mimo to każde poważne wdrożenie RoCE ma plan wyjścia z takiej sytuacji.
Sensem nowoczesnej kontroli przeciążenia w AI jest utrzymanie buforów na tyle małych, żeby PFC nigdy nie odpaliło w stanie ustalonym. PFC pozostaje uzbrojone jako zabezpieczenie na wypadek prawdziwych mikroskoków. Mechanizmem, który nie pozwala mu odpalić, jest DCQCN.
DCQCN — standardowa kontrola przeciążenia dla RoCEv2
DCQCN (DataCenter Quantized Congestion Notification) to algorytm, na którym zbiegło się bezstratne RoCE. Opracowany przez Microsoft i Mellanox (SIGCOMM 2015). W latach 2025–2026 jest tym, co karty ConnectX/BlueField firmy NVIDIA uruchamiają domyślnie, i tym, co Azure raportuje jako standard produkcyjny obejmujący „~85% ruchu Azure, RDMA, we wszystkich regionach publicznych”.
DCQCN ma trzy role: CP (Congestion Point) to przełącznik, który znakuje pakiety przez ECN, gdy głębokość kolejki wyjściowej przekroczy próg (probabilistycznie od 0% przy Kmin do Pmax przy Kmax); NP (Notification Point) to karta odbiorcy, generująca CNP (Congestion Notification Packet) z powrotem do nadawcy po otrzymaniu oznaczeń ECN (z ograniczeniem częstości, zwykle jeden na 50 µs na strumień); RP (Reaction Point) to karta nadawcy, która multiplikatywnie zmniejsza przepływność danego QP po otrzymaniu CNP, a pod jego nieobecność zwiększa ją addytywnie, a potem hiperaddytywnie.
Typowa konfiguracja przełącznika dla DCQCN na 100 GbE:
# Profil ECN w stylu NVIDIA Cumulus na bezstratnym priorytecie RoCE (priorytet 3)
interface swp1..swp32
qos remark dscp-to-tc 26 to 3 # DSCP 26 → TC 3
qos congestion-mark ecn priority 3
qos ecn-kmin 5KB # początek znakowania
qos ecn-kmax 200KB # znakowanie na poziomie Pmax
qos ecn-pmax 1%
qos pfc priority 3
qos pfc xoff 400KB # pauza PFC (znacznie powyżej Kmax)
qos pfc xon 300KB
Kmin/Kmax/Pmax to najczęściej strojona trójka w RoCE. Kmin ma być mały (kilka pakietów), żeby ECN zadziałało przed wyczerpaniem bufora; Kmax znacznie większy, żeby znakowanie narastało stopniowo; próg pauzy PFC znacznie powyżej Kmax, żeby PFC odpalało tylko wtedy, gdy DCQCN zareagowało za wolno. Pierwotne wdrożenie Microsoftu: Kmin = 5 KB, Kmax = 200 KB, Pmax = 1%.
Znane słabości DCQCN: załamanie przy incaście (100 nadawców uderza w jednego odbiorcę, kolejka zapełnia się szybciej, niż CNP wracają, odpala PFC — odpowiedzią jest DCQCN+); niesprawiedliwość w długim ogonie (strumienie startujące później są dławione dłużej); wrażliwość na parametry (Kmin dostrojone dla 4 węzłów nie przenosi się na 64). Uczciwe podsumowanie: DCQCN jest ustawieniem domyślnym, bo działa w większości przypadków. HPCC, Swift, EQDS i odnowione TIMELY istnieją jako propozycje zastąpienia go, ale żadna nie wyparła go do 2026 roku.
ECN, DCTCP i miejsce czystego TCP
Rozdzielmy to czysto, bo te pojęcia bywają mylone:
- ECN — mechanizm warstwy IP (RFC 3168), w którym przełączniki znakują zamiast gubić. To sygnał, sam z siebie nic na niego nie reaguje.
- DCQCN — reakcja punktu końcowego RDMA. Odczytuje ECN przez CNP i dostosowuje przepływność.
- DCTCP — reakcja punktu końcowego TCP. Odczytuje ECN w ACK-ach i skaluje okno proporcjonalnie do udziału oznaczonych pakietów. Microsoft i Stanford, SIGCOMM 2010, dostępne w Windows Server i Linuksie.
| Ruch | Protokół | Kontrola przeciążenia |
|---|---|---|
| Gradienty GPU-GPU (allreduce, NCCL po RoCE) | RoCEv2 | DCQCN (ECN + CNP + przepływność) |
| Pamięć masowa (NFS/RDMA, BeeGFS po RDMA) | RoCEv2 | DCQCN |
| Pamięć masowa (NFS po TCP, S3 do magazynu obiektów) | TCP | DCTCP (albo BBR, albo CUBIC) |
| Kubernetes / orkiestracja / warstwa sterowania | TCP | Domyślnie CUBIC, DCTCP po dostrojeniu |
| Telemetria / Prometheus / SSH | TCP | CUBIC |
Kto pracuje na czystej strukturze RoCE, ten pracuje na DCQCN — warto znać swoje ustawienia domyślne. Jeśli na tym samym łączu jest także pamięć masowa i warstwa sterowania po TCP, warto włączyć DCTCP (net.ipv4.tcp_ecn = 1 plus przełączniki świadome ECN).
Dlaczego ruch AI obciąża to wszystko bardziej niż klasyczne centrum danych
Trzy cechy, pod które klasycznej kontroli przeciążenia nie projektowano:
- Zsynchronizowane skoki. Wszystkie GPU zaczynają allreduce w tej samej nanosekundzie. Od zera do 100% wykorzystania w mikrosekundach. Nie ma rozbiegu, w którym slow start znalazłby właściwą przepływność. Właśnie dlatego DCQCN startuje z prędkością łącza.
- Niewiele dużych strumieni. Prawo wielkich liczb nie przychodzi z pomocą. 8 strumieni → częste kolizje ECMP; 8 odbiorców → dotkliwe blokowanie czoła kolejki przez PFC.
- Ścieżką krytyczną jest najwolniejsze łącze. Czas kroku allreduce = maksymalny czas ukończenia strumienia. Nie ma „przypadku średniego”. Jednoprocentowe prawdopodobieństwo złej kolizji kumuluje się przez miesiące trenowania.
Dlatego ludzie od HPC i AI mają obsesję na punkcie sieci w sposób, jakiego operatorzy skali webowej historycznie nie mieli. Sieć webowa jest elastyczna — wolne żądania oznaczają, że część użytkowników poczeka chwilę dłużej. Trenowanie AI takie nie jest — całe zadanie biegnie z prędkością najwolniejszego zsynchronizowanego elementu.
Złożoność bez przełącznika (zapowiedź N05)
N05 omawia topologie bez przełącznika — połączenia bezpośrednie, siatkę, pierścień, torus 2D/3D, teserakt — dla małych klastrów, w których kupowanie przełącznika 100 GbE jest przesadą. Gdy usuwa się przełącznik, każdy węzeł staje się routerem: wiele kart, wiele ścieżek i coś musi wybrać następny skok.
Standardowa odpowiedź w 2026 roku to FRR (FRRouting) na każdym węźle, skonfigurowane w trybie BGP unnumbered. BGP unnumbered używa do sesji adresów link-local IPv6, więc nie trzeba przydzielać adresów IPv4 na każdym łączu. Każdy węzeł ogłasza swój loopback, uczy się loopbacków sąsiadów, a tablica routingu Linuksa wybiera właściwy następny skok.
# Minimalna konfiguracja FRR dla węzła w siatce bez przełącznika:
router bgp 65001
bgp router-id 10.0.0.1
neighbor enp1s0 interface remote-as external
neighbor enp2s0 interface remote-as external
neighbor enp3s0 interface remote-as external
address-family ipv4 unicast
network 10.0.0.1/32 # loopback tego węzła
redistribute connected
exit-address-family
Dwanaście linii na węzeł, ECMP po tylu parach kart, ile węzeł posiada — z tymi samymi zastrzeżeniami co ECMP na przełączniku. W siatce czterowęzłowej kolizje ECMP pojawiają się także po stronie hostów. Można je łagodzić większą liczbą QP albo zaakceptować stratę (przy 4 węzłach niewielką). „Brak przełącznika” nie oznacza „braku złożoności routingu” — przenosi ją na hosty.
Kiedy to ma znaczenie w praktyce
Większość czytelników nie będzie musiała robić nic z powyższych rzeczy.
- 1–4 węzły, jeden przełącznik, RoCE do pamięci masowej i sporadycznego trenowania na wielu GPU: można zostawić przełącznik na ustawieniach domyślnych. Fabryczne progi DCQCN i ECN są w porządku. PFC jest włączone i najpewniej nigdy nie będzie widać pauzy. Kolizje ECMP są realne, ale ich wpływ na przebieg czterowęzłowy to pojedyncze procenty.
- 4–16 węzłów, dedykowany klaster treningowy: należy jawnie włączyć DCQCN, ustawić Kmin/Kmax/Pmax na 5 KB / 200 KB / 1% (poziom bazowy Azure), włączyć skalowanie QP w NCCL oraz monitorować liczniki pauz PFC i częstość CNP. Jeśli pauz PFC przybywa, DCQCN jest zbyt łagodne — trzeba obniżyć Kmin.
- 16+ węzłów lub 1 000+ GPU: routing adaptacyjny zwraca się z nawiązką. Warto kupić Spectrum-X z pasującymi kartami SuperNIC albo InfiniBand i przestać się przejmować ECMP, albo nawiązać współpracę z kimś, kto prowadził strukturę tej skali. Kosztem błędu są miesiące czasu trenowania.
-
Klaster bez przełącznika, dowolnej wielkości: FRR plus BGP unnumbered. 1–2 dni konfiguracji i testów na każde podwojenie liczby węzłów. Największa pułapka to zapomnienie o ECMP po stronie jądra (
net.ipv4.fib_multipath_hash_policy = 1dla haszowania na L4).
Odruch „dokupię pasma, to przeciążenie nigdy nie wystąpi” jest błędny. Zsynchronizowany ruch AI tworzy natychmiastowe zapotrzebowanie z prędkością łącza na każdej ścieżce, niezależnie od liczby spine'ów. Pasmo rozwiązuje problemy przepływności, a nie problemy koordynacji.
Co zrobić dalej
Jeśli cokolwiek z powyższego może dotyczyć danego klastra:
- Zinwentaryzować ruch. RoCE? TCP? Które łącza przenoszą jedno i drugie? Bez wiedzy, które strumienie na tym skorzystają, nie da się dostroić DCQCN.
- Sprawdzić rzeczywiste ustawienia domyślne DCQCN/ECN/PFC w przełączniku. Profile producentów opisane jako „zoptymalizowane pod AI” różnią się drastycznie. Część dostarczana jest z wyłączonym PFC. Część stosuje Kmin = prędkość portu × 5 µs — rozsądna heurystyka, nie zawsze trafna.
- Włączyć liczniki. Pauzy PFC RX/TX, CNP RX/TX, oznaczenia ECN, wykorzystanie poszczególnych łączy ECMP. Bez tego nie da się stwierdzić, czy struktura jest zdrowa pod obciążeniem.
-
Zmierzyć realnym obciążeniem.
nccl-tests/all_reduce_perfpowie w pięć minut więcej niż tydzień syntetycznego iperfa. - Ustalić, czy w ogóle występuje problem kolizji ECMP, zanim wyda się pieniądze na routing adaptacyjny. Większość klastrów 1–16-węzłowych go nie ma; większość klastrów 64+ węzłów ma.
N08 omawia faktyczną konfigurację RDMA — indeksy GID, MTU, zmienne środowiskowe NCCL, strojenie mlx5_core per karta, które zamienia działające łącze RoCE w szybkie. Tam ta teoria zamienia się w polecenia do wpisania.
To część Kentino Wiki, serii referencyjnej o infrastrukturze obliczeniowej AI, robotyce i systemach, które je łączą. Komentarze i sprostowania mile widziane pod adresem info@kentino.com.