Świadomość NUMA i przypisywanie procesorów dla serwerów dedykowanych

16 min czytania - 16 czerwca 2026

hero section cover
Spis treści
  • Świadomość NUMA i przypisywanie procesorów dla serwerów dedykowanych
  • Jak działa NUMA na serwerach wieloprocesorowych
  • Sprawdzanie topologii NUMA w systemie Linux
  • Przypisywanie procesora i zasady dotyczące pamięci
  • Wybór strategii w zależności od obciążenia
  • Ustawienia BIOS-u i jądra, które należy sprawdzić
Udostępnij

Jak sprawdzić topologię NUMA i przypisać obciążenia systemu Linux do odpowiednich rdzeni i pamięci. Obejmuje numactl, taskset, systemd, ustawienia BIOS-u oraz strategie dostosowane do konkretnych obciążeń.

Świadomość NUMA i przypisywanie procesorów dla serwerów dedykowanych

Na każdym serwerze wieloprocesorowym miejsce uruchomienia procesu i lokalizacja jego pamięci to dwie różne kwestie, a ich rozsynchronizacja jest jednym z najprostszych sposobów na utratę wydajności. Znajomość architektury NUMA i przypisywanie procesorów to dwa narzędzia, które pozwalają temu zaradzić. W tym poście omówiono działanie architektury NUMA, sposoby jej sprawdzania w systemie Linux oraz prawidłowe przypisywanie obciążeń dla baz danych, uczenia maszynowego i usług wrażliwych na opóźnienia.

Jak działa NUMA na serwerach wieloprocesorowych

Węzeł NUMA (Non-Uniform Memory Access) to grupa rdzeni procesora połączonych z lokalnym blokiem pamięci RAM za pośrednictwem dedykowanego kontrolera pamięci. Na serwerze dwuprocesorowym zazwyczaj znajdują się dwa węzły. Każdy rdzeń może odczytać dowolny adres, ale dostęp lokalny trwa około 80 ns, podczas gdy przeskok między gniazdami przez Intel UPI lub AMD Infinity Fabric wynosi około 130–150 ns. W większych systemach z większą liczbą gniazd najgorszy węzeł może przekroczyć 250 ns.

Przepustowość wykazuje ten sam wzorzec. System Sapphire Rapids z dwoma gniazdami może utrzymać prędkość około 600 GB/s, gdy rdzenie korzystają z pamięci lokalnej, ale łącze między gniazdami ma znacznie mniejszą przepustowość, więc ruch przechodzący przez nie szybko napotyka wąskie gardło. Procesory o dużej liczbie rdzeni sprawiają, że jest to bardziej szczegółowe: technologia Sub-NUMA Clustering (SNC) firmy Intel oraz Nodes Per Socket (NPS) firmy AMD dzielą każdy gniazdo na wiele domen NUMA, dzięki czemu komputer z „dwoma gniazdami” może z łatwością udostępniać systemowi Linux cztery lub osiem węzłów.

Bez obsługi NUMA harmonogram Linuksa chętnie przenosi wątek między gniazdami, podczas gdy jego zestaw roboczy pozostaje na pierwotnym węźle. Każdy kolejny dostęp staje się zdalny. Widocznym objawem jest wysokie wykorzystanie procesora przy niskiej rzeczywistej przepustowości, ponieważ rdzenie spędzają czas na oczekiwaniu na pamięć. Urządzenia wejścia/wyjścia pogarszają tę sytuację. Karta graficzna lub karta sieciowa jest podłączona do konkretnego korzenia PCIe, który należy do jednego węzła NUMA. Jeśli proces, który ją zasila, działa na innym gnieździe, każdy transfer DMA przechodzi przez interkonekt.

Sprawdzanie topologii NUMA w systemie Linux

Cztery narzędzia obejmują prawie wszystko, czego potrzebujesz:

  • lscpu do szybkiego podsumowania gniazd i węzłów.
  • numactl --hardware do podsumowania pamięci węzłów i macierzy odległości między węzłami.
  • numastat do liczników trafień/błędów na proces.
  • lstopo (z hwloc) do sprawdzania hierarchii pamięci podręcznej i lokalizacji urządzeń PCIe.

Zacznij od numactl --hardware. Zawiera listę każdego węzła, rdzeni i pamięci do niego należących oraz macierz odległości. Wartość 10 oznacza lokalność, a 20+ – odległość. Jeśli widzisz pojedynczy węzeł na komputerze z wieloma gniazdami, oznacza to, że w BIOS-ie włączona jest funkcja przeplatania węzłów (Node Interleaving) i ukrywa ona topologię — najpierw to napraw (patrz poniżej).

Dla konkretnego procesu numastat -p <PID> przedstawia, gdzie faktycznie przydzielona jest jego pamięć. Istotne są cztery liczniki:

  • numa_hit: pamięć przydzielona na docelowym węźle. Chcesz, aby ta wartość była wysoka.
  • numa_miss: docelowy węzeł był pełny, alokacja została przeniesiona gdzie indziej.
  • numa_foreign: inny węzeł próbował przydzielić pamięć lokalnie, ale nie udało się, co wskazuje na obciążenie pamięci.
  • other_node: strony przydzielone na węźle innym niż ten, na którym działa proces. Wysokie wartości w tym przypadku są klasycznym objawem złego przypisania.

W przypadku obciążeń GPU lub NIC uruchom lstopo-no-graphics i sprawdź, do którego węzła NUMA jest podłączone każde urządzenie PCIe. Jeśli rdzenie sterujące urządzeniem znajdują się na innym węźle, to jest to pierwsza rzecz, którą należy naprawić.

Przypisywanie procesora i zasady dotyczące pamięci

Przypisanie procesora (lub powinowactwo procesora) wiąże proces z konkretnymi rdzeniami, dzięki czemu harmonogram nie może go przenieść. Samo to nie wystarczy, ponieważ system Linux domyślnie stosuje politykę pamięci „first-touch”: strony są przydzielane do tego węzła, który jako pierwszy do nich zapisuje. Jeśli wątek uruchomi się na niewłaściwym węźle, zanim zostanie przypisany, jego pamięć pozostaje tam. Należy kontrolować zarówno rozmieszczenie, jak i alokację.

Trzy narzędzia obejmują typowe przypadki:

NarzędzieFunkcjeZastosowanie
tasksetTylko rdzenie procesoraSzybkie jednorazowe powiązanie istniejącego procesu
numactlRdzenie procesora i pamięćUruchamianie obciążeń z ścisłą lokalnością
systemdRdzenie procesora i pamięć, trwałeUsługi wymagające przypisania przy ponownym uruchomieniu

numactl obsługuje cztery zasady pamięci:

  • --membind=N: przydzielaj tylko na węźle N, w przypadku zapełnienia zgłoś błąd.
  • --preferred=N: preferuj węzeł N, w razie potrzeby przejdź do innych.
  • --interleave=all: algorytm round-robin między węzłami w celu równomiernego rozłożenia przepustowości.
  • --localalloc: przydzielaj na dowolnym węźle, na którym znajduje się uruchomiony procesor.

Przypisanie obciążenia do jednego węzła

Najpierw określ, które rdzenie należą do docelowego węzła:

numactl --hardware

Następnie uruchom aplikację przypisując ją do tego węzła zarówno pod względem rdzeni, jak i pamięci:

numactl --cpunodebind=0 --membind=0 ./your_application

W przypadku już uruchomionego procesu dostosuj przynależność procesora za pomocą taskset:

taskset -cp 0-7 <PID>

Aby zachować te ustawienia po ponownym uruchomieniu systemu, skonfiguruj je w jednostce systemd:

[Service]
CPUAffinity=0-7
NUMAPolicy=bind
NUMAMask=0

Przeładuj i uruchom ponownie:

sudo systemctl daemon-reload && sudo systemctl restart <service>

Podczas ręcznego przypisywania wyłącz automatyczny balanser jądra, aby nie kolidował z Twoim rozmieszczeniem:

sysctl -w kernel.numa_balancing=0

Dodaj to do /etc/sysctl.conf , aby zachować ustawienia. Następnie zweryfikuj za pomocą numastat -p <PID> przez kilka minut rzeczywistego obciążenia. Jeśli other_node wartość pozostaje bliska zeru, przypisanie działa.

Wybór strategii w zależności od obciążenia

Właściwa polityka zależy od tego, czy dla danego obciążenia bardziej korzystne jest niskie opóźnienie, czy łączna przepustowość we wszystkich węzłach.

ObciążeniePolitykaDlaczego
Bazy danych (PostgreSQL, MySQL, SQL Server)--cpunodebind + --membindDuże bufory współdzielone, ścieżki zapytań wrażliwe na opóźnienia
Pamięć podręczna w pamięci (Redis, Memcached)Powiązanie z pojedynczym węzłemWszystko odbywa się poprzez dostęp do pamięci RAM, opóźnienia zdalne są natychmiast widoczne
Szkolenie i wnioskowanie AI/MLPowiązanie z węzłem NUMA procesora graficznegoUnika transferów tensorów przekraczających granice PCIe
Analizy (Spark, Elasticsearch)--interleave=allDuży zestaw roboczy wymaga przepustowości we wszystkich węzłach
Interfejsy API wrażliwe na opóźnienia, handelŚcisła przynależność pinów + IRQPrzewidywalność ma większe znaczenie niż szczytowa przepustowość
Duże obciążenie sieci (RoCEv2, InfiniBand)Pin do węzła NUMA karty sieciowej, dedykowane rdzenie dla IRQUtrzymuje przetwarzanie przerwań lokalnie i z dala od wątków aplikacji

W przypadku obciążeń GPU w szczególności uruchom lstopo , aby sprawdzić, na którym węźle NUMA znajduje się GPU, a następnie uruchom proces uczenia lub wnioskowania z numactl --cpunodebind=N --membind=N dla tego samego N. Jest to jedna z najłatwiejszych metod uzyskania korzyści na wieloprocesorowym serwerze z GPU, ponieważ domyślne rozmieszczenie w harmonogramie jest często błędne.

W przypadku obciążeń HPC i MPI, które obejmują oba gniazda, przypnij każdy rang do pojedynczego węzła za pomocą localalloc zamiast przeplatać wszystko. Każdy rang otrzymuje pamięć lokalną, a równoległość zachodzi na poziomie rangi.

Jedna praktyczna uwaga: jeśli przypisujesz do pojedynczego węzła, zostaw na nim 2–4 GB wolnego miejsca. Węzeł działający na granicy pojemności uruchamia odzyskiwanie pamięci, co kosztuje cię opóźnieniem, którego właśnie próbowałeś uniknąć.

Ustawienia BIOS-u i jądra, które należy sprawdzić

Dokładność wyników narzędzia zależy od topologii ujawnionej przez oprogramowanie układowe. Kilka ustawień, które należy sprawdzić:

  • Przeplatanie węzłów: wyłącz je. Gdy jest włączone, BIOS przedstawia całą pamięć jako jedną płaską pulę i całkowicie ukrywa NUMA przed systemem operacyjnym. numactl --hardware W takim przypadku na komputerze z wieloma gniazdami zostanie wyświetlony jeden węzeł.
  • Klasteryzacja Sub-NUMA (Intel) lub Węzły na gniazdo (AMD): włącz na procesorach z dużą liczbą rdzeni, jeśli chcesz uzyskać lepszą lokalizację. Potwierdza się lscpu po ponownym uruchomieniu.
  • vm.zone_reclaim_mode: ustaw na 0 dla większości serwerów produkcyjnych. Wartość niezerowa agresywnie odzyskuje pamięć lokalną zamiast alokować ją zdalnie, co może spowodować usunięcie przydatnej pamięci podręcznej stron.
  • kernel.numa_balancing: pozostaw włączone dla obciążeń ogólnego przeznaczenia, wyłącz podczas ręcznego przypinania. Automatyczny balanser będzie migrował strony i wątki w sposób sprzeczny z twoją polityką.

Jeśli przeprowadzasz dostrajanie NUMA na sprzęcie typu bare metal, gdzie kontrolujesz BIOS, parametry jądra i przypisanie IRQ, możesz zastosować wszystkie powyższe rozwiązania bez konieczności omijania abstrakcji hiperwizora. To główny powód, dla którego tego rodzaju praca jest łatwiejsza na dedykowanym sprzęcie niż w chmurowych maszynach wirtualnych.

W przypadku serwerów dedykowanych z wieloma gniazdami i pełnym dostępem do konta root, zobacz serwery dedykowane FDC.

Blog

Polecane w tym tygodniu

Więcej artykułów
Dostrojone profile dla optymalizacji obciążenia serwerów Linux

Dostrojone profile dla optymalizacji obciążenia serwerów Linux

Jak wybrać, zastosować i dostosować dostrojone profile dla GPU, baz danych i serwerów Linux o wysokiej przepustowości, z przykładami i wskazówkami dotyczącymi wdrażania Ansible.

16 min czytania - 9 czerwca 2026

Linux OOM Killer Tuning dla VPS: Praktyczny przewodnik

12 min czytania - 8 czerwca 2026

Więcej artykułów
background image

Masz pytania lub potrzebujesz niestandardowego rozwiązania?

icon

Elastyczne opcje

icon

Globalny zasięg

icon

Natychmiastowe wdrożenie

icon

Elastyczne opcje

icon

Globalny zasięg

icon

Natychmiastowe wdrożenie