Anatomia opóźnień: gdzie znika każda mikrosekunda w sieci klastra AI

Osoby dobierające sieć dla klastra AI zwykle zaczynają od przepustowości — 100, 200, 400 GbE — a potem dziwią się, że benchmark allreduce pokazuje wynik daleki od prędkości łącza. Powód to niemal zawsze opóźnienie i reżim małych komunikatów, w którym wykresy przepustowości są bezużyteczne.

Ten artykuł rozkłada pojedynczy cykl tam i z powrotem na części i rozlicza każdy etap. Podane niżej liczby to zgodny zakres z publicznych pomiarów, dokumentacji NVIDIA/Mellanox oraz naszych własnych testów. Należy je traktować jak budżet, a nie gwarancję — zmieniają się wraz z krzemem karty sieciowej, układem ASIC przełącznika, wersją jądra, ustawieniami BIOS-u i cierpliwością przy strojeniu.

Dla kogo: dla osób specyfikujących lub diagnozujących sieci klastrów AI. To nie jest książka kucharska strojenia, lecz model myślowy, dzięki któremu taka książka staje się czytelna.

Pełny cykl tam i z powrotem na jednym slajdzie

64-bajtowy ping-pong między dwoma GPU na różnych węzłach, przez przełączaną sieć 100 GbE z RDMA, rozkłada się mniej więcej tak:

Element Typowy udział Uwagi
Wystawienie / serializacja w aplikacji 0,1–1 µs memcpy, budowa nagłówka, zapis deskryptora
Ścieżka TX karty sieciowej (verbs RDMA) 0,3–0,8 µs poniżej µs na nowoczesnych ConnectX / BlueField
Opóźnienie na kablu ~5 ns/m 50 ns na 10 m DAC, pomijalne przy <100 m
Przeskok przez przełącznik (cut-through, nowoczesny) 250–600 ns InfiniBand <100 ns; Ethernet 400–600 ns
Przeskok przez przełącznik (store-and-forward, 64 B) 1–3 µs Do tego dochodzi serializacja na bajt
Każdy dodatkowy przeskok +opóźnienie przełącznika Leaf-spine dokłada 2 przeskoki względem jednego przełącznika
Ścieżka RX karty sieciowej 0,3–0,8 µs Symetryczna z TX przy RDMA
Stos TCP/IP jądra (w jedną stronę) 10–30 µs Ścieżka gniazd; z przerwaniami i kopiowaniem
Omijanie jądra (DPDK / verbs RDMA, w jedną stronę) <1 µs Odpytywanie w przestrzeni użytkownika, zero kopii
Odbiór / deserializacja w aplikacji 0,1–1 µs Wybudzenie konsumenta, dekodowanie nagłówka

Cykl RTT po RDMA przez jeden przełącznik na 100 GbE / NDR InfiniBand wypada w okolicy ~2 µs dla małych komunikatów. Dwuprzeskokowy leaf-spine dokłada ~1 µs. Ta sama ścieżka przez stos TCP/IP jądra to 20–60 µs, czyli rząd wielkości więcej, przy gorszym zachowaniu ogona rozkładu. Te dwie liczby przesądzają o niemal każdej decyzji architektonicznej opisanej niżej.

Aplikacja TX
memcpy, deskryptor
0,1–1 µs
→NIC TX
Przełącznik
cut-through
250–600 ns
→NIC RX
Aplikacja RX
dekodowanie, wybudzenie konsumenta
0,1–1 µs

Ścieżka RDMA w jedną stronę: przeskok przez przełącznik (250–600 ns na Ethernecie, <100 ns na IB) jest dominującą zmienną; opóźnienie na kablu przy <100 m jest pomijalne.

Problemem nie jest kabel

Światło we włóknie biegnie z prędkością ok. dwóch trzecich c, więc propagacja to ~5 ns/m. 30-metrowe włókno wzdłuż rzędu szaf dokłada 150 ns w jedną stronę; nawet 500-metrowy przebieg kampusowy to jedna mikrosekunda. Serializacja przy dzisiejszych prędkościach też jest niewielka: 64-bajtowa ramka przy 100 Gb/s to 5,12 ns, a ramka jumbo 9000 bajtów to 720 ns. Dla małych komunikatów sterujących serializacja jest pomijalna; przy transferze masowym przestaje mieć znaczenie, gdy tylko łącze jest dostatecznie szerokie.

Opóźnienie mieszka w oprogramowaniu, w układach ASIC przełączników i w wybranym protokole.

Sieć przełączników: cut-through kontra store-and-forward

Przełącznik cut-through zaczyna przesyłać ramkę, gdy tylko odczyta nagłówek z adresem docelowym. Przełącznik store-and-forward buforuje całą ramkę, opcjonalnie sprawdza CRC, a dopiero potem ją przesyła.

Klasa przełącznika Opóźnienie na przeskok
Przełącznik InfiniBand NDR/HDR (cut-through) <100 ns
Ethernet cut-through (klasa Tomahawk, sieci AI) 400–600 ns
Ethernet cut-through (starszy / zwykły) 600–900 ns
Ethernet store-and-forward, 64 B 1–3 µs
Ethernet store-and-forward, 1500 B 1,5–4 µs

Przewaga InfiniBandu jest realna: krzem HPC optymalizuje to od dwóch dekad. Nowoczesne przełączniki Ethernet dla AI (Tomahawk 5, Jericho3-AI, Spectrum-X) nadrabiają większość różnicy w opóźnieniu i wyprzedzają InfiniBand głębokością buforów, która przy incaście w allreduce ma większe znaczenie.

W topologii leaf-spine ruch między szafami przechodzi leaf → spine → leaf. Projekty minimalizujące liczbę przeskoków (płytkie drzewo fat-tree, topologie rail-optimized) nie oszczędzają przepustowości; oszczędzają 500 ns na każdym uniknionym przeskoku przy każdej operacji kolektywnej.

Stos sieciowy jądra

Zwykły TCP/IP przez jądro Linuksa płaci za każdy pakiet: obsługą przerwania karty sieciowej (lub odpytywaniem NAPI), alokacją skb i softirq, przetwarzaniem TCP/IP, kopiowaniem bufora gniazda między jądrem a przestrzenią użytkownika oraz przełączeniem kontekstu do aplikacji.

Dla małego pakietu na nowoczesnym x86 to 10–30 µs w jedną stronę w najlepszym razie, z pikami ogona powyżej 100 µs pod obciążeniem. Jest to też ograniczone przez CPU — nasyca rdzeń przy ~1 Mpps na długo przed kartą sieciową. To właśnie ten koszt próbuje wyeliminować reszta artykułu.

Omijanie jądra: DPDK, RDMA, XDP, AF_XDP

Są cztery główne sposoby na usunięcie jądra ze ścieżki danych, różniące się stopniem obejścia i tym, co przy okazji tracą:

Ścieżka Dolna granica opóźnienia Model CPU Zgodność Typowe zastosowanie
TCP/IP w jądrze 10–30 µs/stronę Przerwania Uniwersalna Wszystko, co nie jest wrażliwe na opóźnienia
AF_XDP 6–10 µs/stronę Hybrydowy Narzędzia Linuksa nadal działają Złoty środek; programy eBPF
DPDK 1–3 µs/stronę Odpytywanie aktywne Jądro nie widzi nic Telko, HFT, NFV, własne potoki pakietów
Verbs RDMA <1 µs/stronę Para kolejek / CQE Wymaga karty i sieci RDMA HPC, trening AI, sieci pamięci masowej

Kilka uwag praktycznych:

  • DPDK i RDMA nie są wymienne. DPDK uruchamia dowolne przetwarzanie pakietów w przestrzeni użytkownika z prędkością łącza; RDMA realizuje konkretny protokół o semantyce pamięciowej z odciążeniem sprzętowym. Obciążenia AI potrzebują RDMA — NCCL i stosy pamięci masowej mówią nim natywnie. DPDK pojawia się w proxy inferencyjnych, telemetrii i własnych warstwach danych.
  • AF_XDP to złoty środek. Wpina się w sterownik na poziomie eBPF, osiąga opóźnienia poniżej 10 µs i — w odróżnieniu od DPDK — nie zabiera karty sieciowej systemowi operacyjnemu. Właściwa odpowiedź dla maszyn o mieszanym przeznaczeniu.
  • XDP bez AF_XDP służy do odrzucania, przekierowywania i przesyłania w locie (oczyszczanie DDoS, równoważenie obciążenia). Przetwarza pakiety wewnątrz jądra na haku sterownika; nie przenosi ich do przestrzeni użytkownika.

Dla klastra AI: RDMA po InfiniBandzie lub RoCEv2 dla komunikacji GPU–GPU, zwykły TCP/IP do całej reszty (zarządzanie, telemetria, pobieranie modeli). Nie warto przeinżynierowywać wolnych ścieżek.

Łączenie przerwań, GRO/LRO: pułapka przepustowości

Linux i większość sterowników kart sieciowych są domyślnie strojone pod przepustowość, nie pod opóźnienie. Znaczenie mają dwa pokrętła:

  • Łączenie przerwań. Karta czeka skonfigurowane okno w µs (albo określoną liczbę pakietów), zanim zgłosi przerwanie. Zmniejsza to narzut na pakiet, ale dokłada opóźnienie równe temu oknu. rx-usecs 50 dokłada do 50 µs na spokojnym łączu.
  • GRO / LRO. Jądro (GRO) lub karta (LRO) scala przychodzące segmenty TCP w jeden większy skb przed przekazaniem wyżej. Przetwarzanie jest tańsze, ale agregator celowo czeka na kolejne pakiety, dokładając mikrosekundy.

Kompromis jest uczciwy i nie podlega negocjacji: nie da się mieć jednocześnie szczytowej przepustowości i szczytowego opóźnienia w tej samej konfiguracji. W węźle GPU karta RDMA obsługująca allreduce chce rx-usecs 0 albo 1, wyłączonego adaptacyjnego łączenia przerwań i wyłączonego GRO na interfejsie po stronie RDMA. Osobna karta zarządzająca zostaje na ustawieniach domyślnych; nie leży na ścieżce krytycznej.

Wniosek: karta sieciowa obsługująca jednocześnie kolektywy RDMA i pobieranie po TCP da mierne wyniki w obu zastosowaniach, o ile ruch nie zostanie rozdzielony na kolejki lub interfejsy. Poważne węzły AI mają jedną lub dwie dedykowane karty RDMA (ConnectX-7/8, BlueField-3) plus osobną kartę zarządzającą.

Warstwa aplikacji też nie jest darmowa

Dwa koszty na szczycie stosu rzadko trafiają na diagramy architektury:

  • memcpy. Kopiowanie 4 MB przez memcpy zajmuje ~200 µs na jednym rdzeniu przy ~20 GB/s. Jeśli operacja kolektywna kopiuje dane tensorów do bufora pośredniego przed wystawieniem, spalone zostało więcej czasu niż cały cykl sieciowy. GPUDirect RDMA to omija — karta sieciowa czyta bezpośrednio z pamięci GPU.
  • Serializacja. Protobuf, JSON albo własne ramkowanie dokładają dziesiątki µs przy nietrywialnych ładunkach. W RPC warstwy sterowania to w porządku; w wewnętrznej pętli allreduce to zabójstwo. NCCL unika tego dzięki stałym deskryptorom binarnym i wcześniej zarejestrowanej pamięci.

Jeśli „nastrojony pod RDMA” stos nadal jest wolny, zanim obwini się sieć, warto sprofilować przestrzeń użytkownika. Widzieliśmy kolektywy trwające 30 µs, z czego 25 µs zajmowało przekształcenie tensora w PyTorchu, a tylko 5 µs kabel i przełącznik.

Operacje kolektywne: opóźnienie kontra przepustowość i dlaczego rozmiar pakietu ma znaczenie

NCCL (i każda biblioteka kolektywów) dobiera algorytm w zależności od rozmiaru komunikatu:

  • Małe komunikaty są ograniczone opóźnieniem. NCCL używa algorytmów drzewiastych i swojego protokołu LL (4 bajty danych z 4 bajtami flag przez 8-bajtowe zapisy atomowe, bez barier pamięci). BusBw stanowi ułamek prędkości łącza; mierzony jest narzut na komunikat × liczba komunikatów.
  • Duże komunikaty są ograniczone przepustowością. NCCL przełącza się na algorytmy pierścieniowe zbliżające się do prędkości najwolniejszego łącza. Opóźnienie na komunikat ginie pod megabajtami.

Przejście leży mniej więcej między 64 KB a 1 MB, zależnie od topologii i karty sieciowej. Poniżej dominują opóźnienia przełącznika, karty i stosu protokołów. Powyżej odczytuje się z wykresu prędkość łącza.

BusBw dla allreduce — klastry jednoszafowe H100 / NDR InfiniBand
Rozmiar komunikatu Algorytm BusBw (jeden węzeł, 8× NVLink) BusBw (8 węzłów, NDR IB)
1 KB Drzewo / LL ~5 GB/s ~2 GB/s
64 KB Drzewo ~80 GB/s ~20 GB/s
1 MB Pierścień ~250 GB/s ~40 GB/s
64 MB Pierścień ~370 GB/s ~45 GB/s
1 GB Pierścień ~450 GB/s ~48 GB/s

Publikowany sufit NVLink dla H100 to 450 GB/s; dojście do niego przy mniejszych komunikatach albo między węzłami to walka ze strojeniem. Dla oferty Kentino — 5090 / 4090 / RTX Pro 6000 Blackwell po 100 GbE RoCE — przy dużych komunikatach na 100 GbE należy spodziewać się ~10–12 GB/s busbw na węzeł, przy tym samym kształcie krzywej.

Jitter jest gorszy niż opóźnienie

Jeżeli opóźnienie allreduce na każdym węźle wynosi 30 µs ± 1 µs, bariera czeka 30 µs. Jeżeli średnia wynosi 30 µs, ale jeden węzeł raz na tysiąc iteracji zrobi 300 µs, każdy inny GPU stoi bezczynnie przez 270 µs za każdym razem, gdy ogon się odezwie. W epoce 100 tys. iteracji na 16 węzłach to godziny utraconych obliczeń.

Dlatego w treningu AI opóźnienie P99 / P999 liczy się bardziej niż średnia. Bariera kolektywna to operacja, w której wygrywa najwolniejszy: klaster porusza się z prędkością swojego najgorszego węzła.

Źródła jittera:

  • Zatory buforów przy incaście. AllReduce to w każdej iteracji ruch wielu do jednego. Przełączniki z płytkimi buforami gubią pakiety, wchodzi pauza PFC, a opóźnienie skacze 10–100×. Przełączniki AI z głębokimi buforami (Jericho3-AI, Spectrum-X) pochłaniają taki impuls.
  • Jitter CPU hosta. Zadanie cron, nieograniczony wątek jądra albo skok częstotliwości CPU dają wartość odstającą rzędu 1 ms. Należy izolować rdzenie dla wątku ISR/odpytywania karty sieciowej, wyłączyć stany C na krytycznych procesorach i przypiąć procesy.
  • Adaptacyjne łączenie przerwań. Sterownik „pomaga”, zwiększając łączenie pod obciążeniem; opóźnienie skacze po cichu. Na karcie RDMA należy to jawnie wyłączyć.
  • Asymetria topologii. Jeden przełącznik leaf na 200 GbE, drugi na 100 GbE. Ten wolniejszy wyznacza podłogę dla każdej operacji kolektywnej.

Właściwym SLO dla sieci AI jest opóźnienie ogona, a nie opóźnienie średnie.

Jak mierzyć poprawnie

ping mierzy RTT ICMP przez stos jądra na płaszczyźnie zarządzania. Jest bezużyteczny do charakteryzowania sieci RDMA. Narzędzia, które się sprawdzają:

  • sockperf ping-pong — pomiar opóźnień UDP/TCP z rozdzielczością poniżej nanosekundy. Dobry do punktów odniesienia dla stosu jądra i do wykrywania regresji.
  • ib_send_lat, ib_write_lat (pakiet perftest) — opóźnienie verbs RDMA wprost. To liczba, która naprawdę ma znaczenie dla InfiniBandu i RoCE. Na łączu w obrębie jednego przełącznika należy spodziewać się ~1–2 µs.
  • Mikrobenchmarki OSU — osu_latency, osu_bw, osu_allreduce na poziomie MPI. Właściwe narzędzie dla aplikacji HPC, zanim do gry wejdzie NCCL.
  • nccl-tests — all_reduce_perf, all_gather_perf, reduce_scatter_perf. Jedyny benchmark, który ma znaczenie dla treningu AI. Wykorzystuje dokładnie tę ścieżkę kodu, z której korzysta dany trening. Warto przejechać zakres od 8 B do 1 GB; krzywa pokaże, gdzie sieć jest zepsuta.

Kontrola zdrowego rozsądku: jeśli busbw z nccl-tests all_reduce_perf przy dużych komunikatach wyraźnie nie dociąga do 80% prędkości łącza karty sieciowej, problem leży w sieci, a nie w oprogramowaniu. Należy przejść warstwy od góry tego artykułu w dół.

Dobry nawyk: zachować wynik nccl-tests jako element odbioru instalacji i powtarzać go po każdej zmianie firmware'u, sterownika lub topologii. Regresja wychwycona tego samego dnia to jednolinijkowy diff. Wychwycona trzy tygodnie później — śledztwo.

Kiedy opóźnienie naprawdę ma znaczenie, a kiedy nie

Opóźnienie ma znaczenie:

  • Synchroniczny allreduce gradientów w treningu z równoległością danych. Każda iteracja, każdy węzeł. Opóźnienie ogona = utracone obliczenia.
  • Drobnoziarnista równoległość potokowa z małymi mikropartiami. Czas bąbla na granicach etapów jest ograniczony od dołu opóźnieniem między węzłami.
  • Podziały warstw w równoległości tensorowej, które rozchodzą się i zbiegają w obrębie jednego przebiegu w przód i w tył — łańcuch małych kolektywów, czysta gra na opóźnieniu.
  • Komunikacja kroku w architekturze parameter server przy wysokiej częstotliwości aktualizacji.

Opóźnienie przeważnie nie ma znaczenia:

  • Batchowanie inferencji na poziomie pojedynczego zapytania. Opóźnienie zapytania zdominowane jest przez obliczenia GPU (TTFT, dekodowanie na token). 10 µs sieci to szum obok 50 ms dekodowania.
  • Masowe ładowanie modelu z pamięci obiektowej przy starcie zadania. Ograniczone przepustowością.
  • Zapis punktu kontrolnego na pamięć sieciową. Duże zapisy sekwencyjne, strojenie pod przepustowość.
  • Tasowanie w DataLoaderze przez prefetch workerów. Wsadowe, ograniczone przepustowością.

Uczciwy wniosek: jednowęzłowy serwer z 4 lub 8 GPU (sztandarowa linia Kentino AI) komunikuje się między GPU po NVLink albo PCIe, a nie przez sieć. Sieć służy do pamięci masowej, telemetrii i sporadycznych eksperymentów wielowęzłowych. Optymalizowanie sieci pod opóźnienie kolektywów zwraca się dopiero przy prawdziwym treningu wielowęzłowym, którego większość klientów Kentino nie prowadzi. Do czystej inferencji i treningu na jednym węźle wystarczy 25 GbE z czystym stosem jądra.

Co dalej

Przy odbiorze nowej sieci warto przejść tę sekwencję:

  1. ib_send_lat między każdą parą węzłów. Wszystko powyżej 1,5× mediany to sygnał ostrzegawczy — zły kabel, brudny wkład optyczny, źle poprowadzona topologia.
  2. nccl-tests all_reduce_perf w zakresie 8 B → 1 GB. Krzywą należy zachować. Następnie porównać ją z publikowanym punktem odniesienia dla danej klasy karty i przełącznika.
  3. Porównać TCP sockperf ping-pong z RDMA ib_send_lat. Różnica powinna wynosić 10–30×. Jeśli jest 2×, albo stos jądra jest wyjątkowo szybki (mało prawdopodobne), albo ścieżka RDMA jest zepsuta (prawdopodobne — zła konfiguracja PFC, zły DCQCN, RDMA schodzące do ścieżki programowej).
  4. Powtórzyć nccl-tests pod obciążeniem. Puścić równolegle ruch do pamięci masowej i obserwować spadek busbw. Zdrowe klastry tracą <20% przy realistycznym ruchu mieszanym; chore się załamują.
  5. Stroić po jednej zmiennej naraz. Łączenie przerwań, routing adaptacyjny, progi PFC, oznaczenia ECN. Każdą zmianę należy udokumentować. Przy trzech zmianach naraz jedna pomoże — tylko nie wiadomo która.
  6. Alarmować na opóźnieniu kolektywów P99, nie na średniej. Średnia ukrywa problem; P99 to jest to, co trening faktycznie odczuwa.

Kontynuacje — N07 o routingu i kontroli zatorów (ECMP, DCQCN, ECN), N08 o wdrażaniu RDMA w praktyce oraz K02 o doborze algorytmu treningu rozproszonego — wchodzą głębiej w konkretne decyzje, które ten artykuł jedynie szkicuje.

Opóźnienie w sieci AI to nie kabel, lecz wszystko, co ten kabel otacza — a lekarstwem jest niemal zawsze skrócenie ścieżki programowej, zanim wyda się więcej na sprzęt.


To część Kentino Wiki, serii referencyjnej o obliczeniach AI, robotyce i systemach, które je łączą. Komentarze i sprostowania prosimy kierować na info@kentino.com.