Ladění jádra Linuxu pro servery s umělou inteligencí: Co vlastně hýbe jehlou
Výchozí jádro Ubuntu na HWE stacku 6.8 nebo 6.11 je dostačující pro zhruba 80 % úloh s umělou inteligencí. Tento článek se týká zbývajících 20 % – vícesocketového EPYC s osmi GPU, serverového serveru vLLM s... vm.max_map_count stěna pod zátěží nebo inferenční server, jehož latence ocasu je spotřebovávána přechody C-stavů CPU.
Většina veřejných rad ohledně „ladění Linuxu pro AI“ je recyklovanými radami z roku 2015 a jejich nezanedbatelný zlomek nenápadně zhoršuje latenci inference. Níže je uvedena menší, ale poctivá sada změn, které skutečně pomáhají na zařízeních třídy Kentino s K-AI (4–8 GPU na Xeonu nebo EPYC, Ubuntu 22.04 / 24.04, jádro 6.x). Předpokládá se, že ovladač a CUDA stack jsou nainstalovány podle... L01 a L02.
Poctivá hierarchie výher
Před jakýmikoli změnami v sysctl se zaměřte na velikost ceny:
| Přeměna | Typické vítězství v inferenci / trénování |
|---|---|
| Umístění procesů s ohledem na NUMA | 10–30 % na vícezásuvkové krabice |
Regulátor CPU performance (Od powersave) |
5–15 % na servírovací krabice, nižší TTFT |
| Zakázání hlubokých C-stavů | Mikrosekundy vypnutí P99, +30–50 W v klidu / patice |
THP nastaveno na madvise
|
1–5 % na PyTorch, méně stání s odchodem zákazníků |
vm.max_map_count, ulimit -n
|
Zabraňuje převrácení servírování pod zátěží |
| Afinita IRQ k lokálnímu uzlu NUMA | 5–15 % na síťových cestách DataLoader / RDMA |
Velikost vyrovnávací paměti TCP (rmem_max, wmem_max) |
Záleží pouze pro úložiště/streamování >25 GbE |
| Vše ostatní | 0–3 %, často šum |
Pokud si z tohoto článku nic dalšího neodnesete: Dvěma velkými výhrami jsou povědomí o NUMA a regulátor CPU. Všechno ostatní je zaokrouhlovací chyba, pokud jste to neměřili.
Regulátor CPU: nejlevnějších 5–15 % na stole
Ubuntu je ve výchozím nastavení powersave (intel_pstate) nebo ondemand (acpi_cpufreq) v závislosti na ovladači. Oba reaktivně nastavují časování, což snižuje náklady na inferenční TTFT a na přípravu na straně CPU kolem dopředného průchodu vLLM – tokenizace, plánování, vzorkování logitů.
Pro servírovací krabici nastavte performance a zapomeňte:
sudo apt install -y cpufrequtils
echo 'GOVERNOR="performance"' | sudo tee /etc/default/cpufrequtils
sudo systemctl restart cpufrequtils
# Verify
for c in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do cat $c; done | sort -u
Na EPYC Genoa / Turin s jádrem 6.5+, amd-pstate řidič nahrazuje acpi-cpufreqStejný nápad, sada scaling_governor na performanceNovější amd-pstate-epp režim udržuje výkon a zároveň umožňuje zvýšení výkonu na jádro; ponechte EPP na performance, Ne balance_performance.
Upozornění: na trénovacím boxu s trvalým využitím GPU ~100% jsou CPU stejně zatíženy a regulátor je méně důležitý. Velkou výhodou jsou inferenční servery, které mezi požadavky nečinně fungují a potřebují okamžitě nastartovat.
NUMA: rozdíl mezi rychlým a průměrným EPYC boxem
Jednosocketové servery Xeon nebo EPYC nemají o čem přemýšlet – jeden uzel NUMA, každý přístup k paměti je lokální. Dvousocketové servery jsou místem, kde žije těch 10–30 %.
Výchozí plánovač s radostí umístí vLLM worker na socket 0 a přesměruje ho do paměti alokované na socketu 1 pomocí page fault – každé načítání je cross-socket UPI / Infinity Fabric hop. Pro model se stovkami GB vah procházených jednou na token je to reálné.
Kontrolovat:
numactl --hardware # node count, sizes, distance matrix
nvidia-smi topo -m # GPU↔CPU NUMA affinity
cat /sys/class/net/<iface>/device/numa_node # NIC NUMA affinity
Vzor, který chcete – a který NCCL detekuje automaticky – je GPU N připnutý k uzlu NUMA, který hostuje jeho kořenový komplex PCIe, nikoli k druhému socketu. Pro ručně spuštěný inferenční proces připněte CPU i paměť k lokálnímu uzlu:
# vLLM on a 2-socket EPYC, GPUs 0–3 on NUMA node 0
numactl --cpunodebind=0 --membind=0 \
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.3-70B-Instruct --tensor-parallel-size 4
Dva související knoflíky:
-
kernel.numa_balancingmigruje stránky směrem k CPU, které se jich dotýká. Užitečné pro obecné úlohy, občas kontraproduktivní pro AI: předběžné vyplnění jednou projde váhy, jádro migruje stránky a další požadavek je stáhne zpět. Ve výchozím nastavení ponechte zapnuto (1); pokud jitter koreluje snuma_pte_updatesin/proc/vmstat, Snaž sesysctl kernel.numa_balancing=0. -
NCCL na dvouzásuvce — sada
NCCL_SOCKET_IFNAMEk manažerské síťové kartě aNCCL_IB_HCAk síťové kartě (NIC) na stejném uzlu NUMA jako grafické karty (GPU). Špatná síťová karta tiše snižuje propustnost mezi uzly na polovinu.
Jednosocketový server EPYC 9004/9005: celou tuto část ignorujte.
Průhledné obrovské stránky: madvise, Ne always
THP oportunisticky skládá 4KB stránky do 2MB stránek, čímž snižuje tlak na TLB. PyTorch a ovladač CUDA z toho profitují jen mírně. Past je v tom, že... always režim při chlazení paměti — jádro zastaví vlákno na 50–100 ms, čímž zhutní paměť a torpéduje tak jakékoli SLO s latencí.
Správné nastavení je madvise: aplikace, které vědí, co dělají, volají madvise(MADV_HUGEPAGE) na dlouhodobých alokacích a získává THP; nic jiného to nedělá. Nastaveno pomocí /etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="... transparent_hugepage=madvise"
update-grub && rebootDefragmentace by měla odpovídat — defer+madvise umožňuje zhutnění probíhat na pozadí, nikoli v cestě alokačního vlákna:
echo defer+madvise | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
Pro produkční prostředí vLLM / SGLang / TensorRT-LLM, madvise je správná výchozí hodnota. PyTorch s CUDA Unified Memory (výzkumný kód) někdy těží z always – před otočením změřte.
Explicitní 1 GB obrovské stránky: pouze pokud jste změřili
Explicitní obrovské stránky rezervované při bootování přes hugetlbfs poskytnout malou dodatečnou výhodu pro velmi velké váhy LLM eliminací chyb TLB při skenování vah. Háček: paměť je rezervována předem a není k dispozici zbytku systému, aplikace musí být sestavena tak, aby ji používala, a zisk je 1–3 % pro většinu obslužných úloh.
GRUB_CMDLINE_LINUX_DEFAULT="... default_hugepagesz=1G hugepagesz=1G hugepages=64"
Stojí to za to pro TensorRT-LLM box, kde se engine vejde do zapnuté paměti a vy se honíte za posledními procenty TTFT. Nestojí to za to pro obecný vLLM server, který přepíná modely nebo jakýkoli trénovací box. Přeskočit při prvním sestavení; vraťte se pouze, pokud perf stat -e dTLB-load-misses ukazuje tlak TLB a máte rezervu v RAM.
vm.max_map_count a nofile: stěny, které vLLM zasahuje ve velkém měřítku
Automaticky vm.max_map_count v Ubuntu je to 65530 – počet různých mapování paměti, které může proces uchovávat. vLLM obsluhující rozsáhlý model s vysokou souběžností nebo jakýkoli framework využívající mnoho mmapstřepy safetensoru, proletí kolem a umírá Cannot allocate memoryHodnota 262144 odvozená z Elasticsearch je naprosté minimum; pro vLLM obsluhující 70B+ se stovkami souběžných sekvencí je třeba nastavit hodnotu 1048576. Nic to nestojí – jde o měkký limit, ne o rezervaci.
Automaticky ulimit -n na Ubuntu je to 1024. Komicky málo: vLLM, Triton, PyTorch DataLoader workers, NCCL a vrstva gRPC mezi nimi otevírají stovky FD. Dosáhnete limitu a dostanete EMFILE: too many open files a proces, který se tiše zasekává.
# /etc/sysctl.d/99-ai-server.conf
vm.max_map_count = 1048576
# /etc/security/limits.d/99-ai-server.conf
* soft nofile 1048576
* hard nofile 1048576
# /etc/systemd/system.conf.d/99-limits.conf
[Manager]
DefaultLimitNOFILE=1048576
sudo sysctl --system a systemctl daemon-reexecOvěřte u ulimit -n a cat /proc/<pid>/limits.
Afinita IRQ: připínání přerušení síťové karty k lokálním CPU
Na 100GbE síťové kartě ConnectX-6/7, která podporuje streamování datových sad nebo provoz RDMA s rychlostí přes 10 GB/s, musí přerušení přistát na procesorech (a) na stejném uzlu NUMA jako síťová karta a (b) ne na stejných jádrech, na kterých běží workery DataLoader. Výchozí nastavení irqbalance odvádí přijatelnou práci; při velké zátěži ne.
Nejčistší řešení je od Mellanoxu. set_irq_affinity.sh od mlnx-tools:
sudo systemctl disable --now irqbalance
sudo /usr/sbin/set_irq_affinity.sh enp1s0f0 # all NIC-local cores
sudo /usr/sbin/set_irq_affinity_cpulist.sh 4-11 enp1s0f0 # pin to specific cores
Špatným krokem je odejít irqbalance běží na krabici, kterou jste také ručně připnuli – bojují. Vyberte si jednu. Obsluhující krabice s jednou nebo dvěma RDMA síťovými kartami: ručně připnout, zakázat irqbalanceUniverzální krabice s mnoha rozhraními: nechte irqbalance na s --banirq vyloučit kritickou síťovou kartu.
Vyrovnávací paměti síťového jádra: pouze pro rychlé úložiště / streamovací cesty
Pro inferenční server s jedním uzlem, který komunikuje s klienty přes prostý TCP s nízkou rychlostí, je výchozí net.core.rmem_max / wmem_max 208 KB je v pořádku. Pro uzel stahující trénovací data ze 100GbE NFS nebo úložiště objektů, nebo pro frontend vLLM za vyrovnávačem zátěže s vysokým RPS jsou výchozí hodnoty maximální hodnotou pro váš produkt s ohledem na zpoždění šířky pásma. Výchozí sada pro zařízení připojené ke 100GbE:
# /etc/sysctl.d/99-ai-network.conf
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.tcp_rmem = 4096 87380 268435456
net.ipv4.tcp_wmem = 4096 65536 268435456
net.core.netdev_max_backlog = 250000
net.core.somaxconn = 65535
Maximálně 256 MB je pro rackový 100 GbE (BDP je ~1.25 MB) přehnané, ale neškodné – automatické ladění TCP zvětšuje vyrovnávací paměti pouze podle potřeby až do limitu. U RDMA (RoCE / IB) pro datovou cestu tyto knoflíky nehrají roli – RDMA obchází kernelový TCP stack. Stále hrají roli pro rovinu správy, NFS a stahování modelů.
C-stavy: latence vs. klidový výkon
U obslužného zařízení citlivého na latenci je nejlevnějším zlepšením latence ocasu po regulátoru CPU zakázání hlubokých C-stavů. Vstup/výstup C6 je v desítkách mikrosekund; u požadavku, který by měl odpovědět do 30 ms, přidává CPU vycházející z C6 pro zpracování vzorkování po tokenu znatelný jitter.
GRUB_CMDLINE_LINUX_DEFAULT="... intel_idle.max_cstate=1 processor.max_cstate=1"
update-grub && rebootOvěřte u cpupower idle-info — k dispozici by měly být pouze C0 a C1. Cena: 30–50 W klidového výkonu na zásuvku protože jádra nikdy nepřecházejí do hlubokého spánku. Na dvoupaticovém serveru s 8 GPU je to 60–100 W trvalé režie – nepatrné oproti 3.5–4.5 kW trvalé spotřeby GPU při zátěži.
Použijte pro inferenční servery citlivé na latenci a robotické cesty v reálném čase. Přeskočte trénovací boxy (latence nehraje roli, spotřeba energie v nečinnosti se sčítá za měsíce) a dávkové úlohy.
Ladění jádra související se souborovým systémem (náhled na L04)
Několik fs.* sysctls záleží:
fs.aio-max-nr = 1048576 # default 65536 too low for vLLM weight loaders
fs.inotify.max_user_watches = 524288 # tooling that watches checkpoint dirs
fs.aio-max-nr je ten, co kouše – frameworky provádějící asynchronní I/O s mnoha shardy (DALI, zavaděče hmotnosti vLLM) u velkých modelů propalují výchozí hodnotu 65536. Samotná volba souborového systému (XFS vs ZFS vs ext4), možnosti připojení a O_DIRECT sémantika žije v L04.
Zakázání nepotřebných modulů jádra
Bezhlavý server nemá žádné moduly pro načítání bluetooth, zvuku, webkamery, bezdrátového připojení, joysticku ani tiskového serveru. Každý z nich představuje více kódu v útočné ploše a malé zpoždění při spouštění. Jednotlivě triviální; kolektivně je o čistším serveru snazší uvažovat.
# /etc/modprobe.d/blacklist-ai-server.conf
blacklist bluetooth
blacklist btusb
blacklist snd_hda_intel
blacklist uvcvideo
blacklist joydev
# Plus
sudo systemctl disable --now bluetooth.service cups.service avahi-daemon.service \
ModemManager.service whoopsie.service apport.service
Bootování se u typické sestavy EPYC sníží z ~30 s na ~10 s. lsmod stává se čitelným. Nulový dopad na výkon inference, mírné snížení plochy útoku.
Dva profily: inference vs. trénování
Tvar ladění je skutečně odlišný. Náčrty pro zasunutí:
Inference (/etc/sysctl.d/99-ai-inference.conf)
vm.max_map_count = 1048576
vm.swappiness = 1
vm.overcommit_memory = 1
kernel.numa_balancing = 1
fs.aio-max-nr = 1048576
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.tcp_rmem = 4096 87380 268435456
net.ipv4.tcp_wmem = 4096 65536 268435456
net.core.netdev_max_backlog = 250000
net.core.somaxconn = 65535
Navíc na příkazovém řádku jádra: transparent_hugepage=madvise intel_idle.max_cstate=1 processor.max_cstate=1Guvernér: performance. IRQ síťových karet připnuté k lokálním jádrům NUMA, irqbalance vypnuto.
Školení (/etc/sysctl.d/99-ai-training.conf)
vm.max_map_count = 1048576
vm.swappiness = 1
vm.overcommit_memory = 1
kernel.numa_balancing = 0 # page migration mid-epoch is just churn
fs.aio-max-nr = 1048576
fs.inotify.max_user_watches = 524288
net.core.rmem_max = 536870912
net.core.wmem_max = 536870912
net.ipv4.tcp_rmem = 4096 131072 536870912
net.ipv4.tcp_wmem = 4096 131072 536870912
Příkazový řádek jádra: transparent_hugepage=madvise (přeskočit pinning C-state – trénink je omezen propustností, spotřeba v klidu se v průběhu týdnů sčítá). Regulátor: performance pokud máte dostatečný rozpočet. NCCL je připnutý k místní NUMA přes NCCL_IB_HCA.
Past „Všechno jsem naladil a ono se to zpomalilo“
Nejčastějším způsobem selhání je výpis z cargo-cultu: zkopírovat sto sysctlů z blogového příspěvku, restartovat, pozorovat horší výkon a netušit, kterým knoflíkem uvolnit. Metoda, která funguje:
- Stanovení základní linie –
nccl-tests all_reduce_perf, vLLMbenchmark_throughput.py, čas tréninkového kroku. Zapište si čísla. - Změň jednu věc.
- Znovu spusťte stejný benchmark třikrát pro měření šumu.
- Pokud je medián významně lepší, ponechte jej. Pokud ne, vraťte jej zpět.
- Změnu a důvod zdokumentujte ve správě verzí vedle souboru sysctl.
Viděli jsme produkční boxy se 40 řádky ladění sysctl, které byly dohromady o 2 % pomalejší než výchozí nastavení Ubuntu – každá jednotlivá změna byla neutrální nebo horší, ale operátor si byl jistý, že „ladění pomohlo“.
Červený klobouk tuned 2.27 lodí explicitně ai-inference a ai-training profily a je to důvěryhodná zkratka na RHEL / Rocky. Ubuntu ji nedodává; apt install tuned funguje, ale je méně propracované. V Ubuntu ručně vkládané drop-iny v /etc/sysctl.d/ a čistý příkazový řádek GRUBu se snáze audituje a přesně víte, co je nastaveno.
Co dělat dál
Rozumná sekvence ladění jádra pro novou sestavu Kentino K-AI, seřazená podle priority:
-
Nastavte regulátor CPU na
performance. Ověřte ucpupower frequency-infoNejvětší výhra bez jakýchkoli nákladů. -
Běh
numactl --hardwareanvidia-smi topo -m. Před jakýmkoli připojením si promyslete topologii. U dvoupaticových boxů si naplánujte, které grafické karty budou patřit kterému uzlu NUMA. -
sada
vm.max_map_countanofileomezení. Tyto metody zabraňují selháním, nikoli zpomalení. Proveďte je před prvním spuštěním výroby. -
sada
transparent_hugepage=madvisena příkazovém řádku jádra. -
Pin NIC IRQ k lokálnímu uzlu NUMA síťové karty s
set_irq_affinity.sh. Zakázatirqbalancepokud jste tak učinili. -
Pouze pro inferenční rámečky: zakázat hluboké C-stavy pomocí
intel_idle.max_cstate=1 processor.max_cstate=1. - Ladění síťových vyrovnávacích pamětí pouze pokud jste naměřili úzké hrdlo na úložné nebo streamovací trase 25/100 GbE.
- Přeskočit 1 GB explicitních obrovských stránek pokud nemáte benchmark ukazující tlak TLB.
- Benchmark před a po každé změně. Jedna věc po druhé. Dokument.
Křížové odkazy: L01 pro připínání ovladačů a jádra, L02 pro CUDA / kontejnerový stack, L04 pro vrstvu souborového systému, L05 pro sledování.
Ladění jádra v moderním Linuxu je většinou jednorázová konfigurace, nikoli průběžná optimalizační hra. Správně nastavte governor, umístění NUMA a limity. Zbytek přeskočte, pokud váš benchmark neříká jinak.
Toto je součást Kentino Wiki, referenční série o výpočetní technologii s využitím umělé inteligence, robotice a systémech, které je propojují. Komentáře a opravy jsou vítány na adrese info@kentino.com.