...

NUMA Balancing Server: Optymalizacja dostępu do pamięci dla sprzętu hostingowego

Pokazuję, jak Serwer równoważący NUMA na sprzęcie hostingowym usprawnia dostęp do pamięci i zmniejsza opóźnienia poprzez powiązanie procesów i danych z odpowiednim węzłem NUMA. Decydującym czynnikiem jest Optymalizacja dostępu do pamięci poprzez dostęp lokalny, umieszczanie zadań i ukierunkowaną migrację stron do hostów Linux z wieloma rdzeniami.

Punkty centralne

  • NUMA dzieli procesory i pamięć na węzły; dostęp lokalny zapewnia niski Opóźnienie.
  • Automatyczny NUMA Balancing migruje strony i umieszcza zadania blisko węzła.
  • Rozmiar maszyny wirtualnej na węzeł, w przeciwnym razie istnieje ryzyko NUMA Trashing.
  • Narzędzia as numactl, lscpu, numad show Topologia i używać.
  • StrojenieC-States, Node Interleaving from, Ogromne strony, powinowactwa.

Czym jest NUMA - i dlaczego ma znaczenie dla hostingu

NUMA dzieli system wieloprocesorowy na Węzeł, z których każdy zawiera własne procesory i lokalną pamięć, dzięki czemu pobliskie dostępy są szybsze niż zdalne. Podczas gdy UMA wysyła wszystkie rdzenie do wspólnej ścieżki, NUMA zapobiega powstawaniu wąskich gardeł z powodu lokalny kanałów pamięci na węzeł. W środowiskach hostingowych z wieloma równoległymi maszynami wirtualnymi każda milisekunda opóźnienia sumuje się, więc każde żądanie przynosi wymierne korzyści. Jeśli chcesz uzyskać więcej informacji, możesz dowiedzieć się więcej na temat Architektura NUMA. Dla mnie jedno jest pewne: jeśli rozumiesz i używasz węzłów, uzyskujesz większą przepustowość z tego samego sprzętu.

Automatyczne równoważenie NUMA w jądrze Linux - jak to działa?

Jądro okresowo skanuje części przestrzeni adresowej i „niezamapowane“ strony, dzięki czemu błąd podpowiedzi może zostać usunięty. optymalny węzeł widoczny. Jeśli wystąpi błąd, algorytm ocenia, czy warto migrować stronę lub przenieść zadanie i unika niepotrzebnych ruchów. Migrate-on-Fault przynosi Dane bliżej wykonującego procesora, rozmieszczenie zadań NUMA przenosi procesy bliżej ich pamięci. Skaner rozprowadza swoją pracę kawałek po kawałku, tak aby narzut pozostawał w granicach normalnego obciążenia. Skutkuje to ciągłym dostrajaniem, które zmniejsza opóźnienia bez konieczności stosowania sztywnych reguł przypinania.

Optymalizacja dostępu do pamięci: lokalny bije zdalny

Dostęp lokalny wykorzystuje Kontroler pamięci własnego węzła i zminimalizować czas oczekiwania na połączenie. Zdalny dostęp kosztuje cykle za pośrednictwem QPI/UPI lub Infinity Fabric, a tym samym minimalizuje efektywny czas dostępu. Szerokość pasma. Wysoka liczba rdzeni potęguje ten efekt, ponieważ coraz więcej rdzeni konkuruje o te same połączenia. Dlatego planuję tak, aby gorący kod i aktywne dane znajdowały się razem na jednym węźle. Zlekceważenie tej zasady oznacza utratę punktów procentowych, które decydują o czasie odpowiedzi lub przekroczeniu limitu czasu podczas szczytów obciążenia.

Rozmiary maszyn wirtualnych, usuwanie NUMA i przycinanie hosta

Wymiaruję maszyny wirtualne tak, aby jednostki vCPU i pamięć RAM mieściły się w węźle NUMA, aby uniknąć dostępu między węzłami. Często 4-8 jednostek vCPU na węzeł zapewnia dobrą wydajność. Wskaźniki trafień, w zależności od platformy i hierarchii pamięci podręcznej. Duże strony również pomagają, ponieważ TLB działa wydajniej, a migracje stron występują rzadziej. W razie potrzeby ustawiam Przynależność procesora dla procesów krytycznych pod względem opóźnień, aby powiązać wątki z odpowiednimi rdzeniami - więcej informacji można znaleźć na stronie Przynależność procesora. Jeśli maszyny wirtualne są podzielone między węzły, istnieje ryzyko śmieci NUMA, tj. ping-pong danych i wątków.

Narzędzia w praktyce: numactl, lscpu, numad

Z „lscpu“ czytam Topologia i węzły NUMA, w tym przypisanie rdzeni. „numactl -hardware“ pokazuje mi pamięć na węzeł i dostępne odległości, co ułatwia ocenę ścieżek. Demon „numad“ monitoruje wykorzystanie i dynamicznie dostosowuje powinowactwa, gdy centra obciążenia się przemieszczają. W przypadku stałych scenariuszy używam „numactl -cpunodebind/-membind“ do jawnego przypinania procesów i pamięci. W ten sposób łączę automatyczne równoważenie z ukierunkowanymi specyfikacjami i kontroluję wynik za pomocą „perf“, „numastat“ i „/proc“.

Jak mierzę wpływ: Kluczowe liczby i polecenia

Zawsze oceniam NUMA-Tuning poprzez Seria pomiarowa, a nie przeczuciem. Trzy wskaźniki udowodniły swoją wartość: Stosunek odsłon lokalnych do zdalnych, wskaźnik migracji i rozkład opóźnień (P95/P99).

  • W całym systemienumastat„ pokazuje dostęp lokalny/zdalny i zmigrowane strony na węzeł.
  • Związane z procesem: „/proc//numa_maps“ ujawnia, gdzie znajduje się pamięć i jak została rozłożona.
  • Widok harmonogramuCpus_allowed_list„ i rzeczywiste “Cpus_allowed„ sprawdzają, czy mają zastosowanie powiązania.
# Widok całego systemu
numastat
numastat -m

# Dystrybucja i powiązania związane z procesem
pid=$(pidof )
numastat -p "$pid"
cat /proc/"$pid"/numa_maps | head
cat /proc/"$pid"/status | grep -E 'Cpus_allowed_list|Mems_allowed_list'
taskset -cp "$pid"

# Licznik jądra dla aktywności NUMA
grep -E 'numa|migrate' /proc/vmstat

# Śledzenie zdarzeń dla dogłębnych analiz (aktywacja na krótki czas)
echo 1 > /sys/kernel/debug/tracing/events/mm/enable
sleep 5; cat /sys/kernel/debug/tracing/trace | grep -i numa; echo 0 > /sys/kernel/debug/tracing/events/mm/enable

Porównuję w każdym przypadku A/B: unbound vs. bound, automatyczne równoważenie włączone/wyłączone i różne plasterki maszyn wirtualnych. Celem jest wyraźna redukcja zdalnych dostępów i szumu migracji, a także zmniejszenie opóźnień P95/P99. Dopiero gdy zmierzone wartości będą stabilnie lepsze, zajmę się strojeniem.

Ustawienia BIOS i firmware, które naprawdę działają

Wyłączam „Node Interleaving“ w BIOS-ie, aby struktura NUMA pozostała widoczna, a jądro lokalny może planować. Zmniejszona liczba stanów C stabilizuje szczytowe opóźnienia, ponieważ rdzenie rzadziej przechodzą w stan głębokiego uśpienia, co skraca czas wybudzania. Przydzielam kanały pamięci symetrycznie, aby każdy węzeł mógł wykorzystać swoją maksymalną pojemność pamięci. Szerokość pasma osiągnięte. Testuję prefetchery i funkcje RAS za pomocą profili obciążenia, ponieważ pomagają one lub szkodzą w zależności od wzorca dostępu. Mierzę każdą zmianę w stosunku do linii bazowej i dopiero wtedy przyjmuję ustawienie na stałe.

Parametry jądra i sysctl, które robią różnicę

Dopracowanie jądra pomaga mi, Nad głową oraz Czas reakcji balancera, aby dopasować go do obciążenia. Zaczynam od konserwatywnych wartości domyślnych i krok po kroku posuwam się naprzód.

  • kernel.numa_balancingWłączanie/wyłączanie automatycznego wyważania. Pozostawiam ją włączoną dla ruchomych ładunków; wyłączam ją dla ściśle przypiętych specjalnych usług jako test.
  • kernel.numa_balancing_scan_delay_msCzas oczekiwania przed pierwszym skanowaniem po utworzeniu procesu. Wybierz większy, jeśli uruchomionych jest wiele krótkotrwałych zadań; mniejszy dla długo działających usług, które wymagają szybkiej bliskości.
  • kernel.numa_balancing_scan_period_min_ms / _max_msSzerokość pasma interwałów skanowania. Wąskie interwały zwiększają szybkość reakcji, ale także obciążenie procesora.
  • kernel.numa_balancing_scan_size_mbProporcja przestrzeni adresowej na skan. Zbyt duży generuje burze podpowiedzi, zbyt mały reaguje powoli.
  • vm.zone_reclaim_modeJeśli pamięci jest mało, jądro preferuje lokalne odzyskiwanie zamiast zdalnego przydzielania. Dla ogólnych obciążeń hostingu, zwykle zostawiam 0; W przypadku ściśle wrażliwych na opóźnienia usług pamięci lokalnej ostrożnie testuję wyższe wartości.
  • Transparent Huge Pages (THP)Pod „/sys/kernel/mm/transparent_hugepage/{enabled,defrag}“ zwykle ustawiam na madvise i konserwatywna defragmentacja. Twarde profile „zawsze“ przynoszą korzyści TLB, ale ryzykują przeciągnięcia z powodu kompaktowania.
  • sched_migration_cost_nsSzacunkowy koszt migracji zadań. Wyższe wartości tłumią redystrybucję agresywnych schedulerów.
  • cgroups cpusetZ cpuset.cpus oraz cpuset.mems Oddzielam usługi czysto według węzłów i upewniam się, że Pierwsze dotknięcie pozostaje w obrębie dopuszczalnych węzłów.
Przykład #: konserwatywne, ale responsywne równoważenie
sysctl -w kernel.numa_balancing=1
sysctl -w kernel.numa_balancing_scan_delay_ms=30000
sysctl -w kernel.numa_balancing_scan_period_min_ms=60000
sysctl -w kernel.numa_balancing_scan_period_max_ms=300000
sysctl -w kernel.numa_balancing_scan_size_mb=256

# Używaj THP ostrożnie
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo defer > /sys/kernel/mm/transparent_hugepage/defrag

Pozostaje to ważne: Zmieniaj tylko jedną śrubę regulacyjną na rundę testową i testuj efekt w odniesieniu do tej samej krzywej obciążenia. W ten sposób oddzielam przyczynę od skutku.

Prawidłowe pozycjonowanie obciążeń: Bazy danych, pamięci podręczne, kontenery

Bazy danych odnoszą korzyści, gdy pule buforów pozostają lokalne na węzeł NUMA, a wątki są powiązane blisko swoich hałd. W pamięci podręcznej ustawiam sharding na Węzeł aby uniknąć zdalnego pobierania. Platformy kontenerowe odbierają limity i żądania, dzięki czemu pody nie przeskakują między węzłami. Do rezerwacji pamięci używam Huge Pages, co ułatwia przechowywanie hotsetów w Skrytki dopasowanie. Poniższa tabela podsumowuje strategie i typowe efekty w kompaktowej formie.

Strategia Użycie Oczekiwany efekt Wskazówka
Pierwsze dotknięcie Bazy danych, sterty JVM Przydział po stronie lokalnej Wykonanie inicjalizacji na węźle docelowym
Interleave Szeroko rozłożone obciążenie Równomierna dystrybucja Nieoptymalny dla hotspotów
Przypinanie zadań Usługi o krytycznym opóźnieniu Stałe opóźnienie Mniejsza elastyczność podczas zmian obciążenia
Automatyczne wyważanie Mieszane obciążenia Dynamiczna bliskość Ważenie kosztów ogólnych w stosunku do zysku
Ogromne strony Duże hałdy, pamięci podręczne Mniej pominięć TLB Planuj czyste rezerwacje

Wirtualizacja: wirtualne NUMA, scheduler i personalizacja gościa

Virtual NUMA przekazuje topologię hosta do systemu operacyjnego gościa w uproszczonej formie, dzięki czemu pierwszy dotyk i Alokator działają rozsądnie. Harmonogramy hiperwizora zwracają uwagę na bliskość węzłów podczas dystrybucji jednostek vCPU i migracji maszyn wirtualnych. Rzadko wyrównuję duże maszyny wirtualne na wielu węzłach, chyba że obciążenie jest szeroko strumieniowe i korzysta z interleave. W gościach dostosowuję sterty maszyn JVM lub baz danych, aby pozostały lokalne na widocznych węzłach NUMA. Jeśli chodzi o zarządzanie pamięcią w gościach, spójrz na Pamięć wirtualna, aby okiełznać rozmiary stron i zamianę.

Bliskość PCIe: NVMe i karty sieciowe we właściwych węzłach

Jeśli to możliwe, przypisuję dyski SSD NVMe i szybkie karty sieciowe do węzła, na którym znajduje się Obciążenie pracą jest uruchomiony. W ten sposób unikam żądań I/O przekraczających połączenie międzysieciowe i dodających opóźnienia. Wielowątkowe karty sieciowe wiążę z zestawami rdzeni węzła za pomocą RSS/RPS, dzięki czemu IRQ pozostają lokalne. W przypadku stosów pamięci masowej warto podzielić pule wątków węzeł po węźle. Jeśli zwrócisz na to uwagę, zauważalnie zmniejszysz opóźnienia P99 i stworzysz zapas na szczyty obciążenia.

IRQ i powinowactwo kolejek w praktyce

Najpierw sprawdzam, które Węzeł NUMA urządzenia i odpowiednio przypiąć IRQ i kolejki. Zapewnia to utrzymanie lokalności ścieżki danych.

# Mapowanie urządzenie-węzeł
cat /sys/class/net/eth0/device/numa_node
cat /sys/block/nvme0n1/device/numa_node

# Ustaw specyficzne powinowactwo IRQ (przykład: rdzenie 0-7 węzła)
irq=
echo 0-7 > /proc/irq/$irq/smp_affinity_list

# Powiązanie kolejek NIC z rdzeniami (RPS/RFS)
for q in /sys/class/net/eth0/queues/rx-*; do echo 0-7 > "$q"/rps_cpus; done
sysctl -w net.core.rps_sock_flow_entries=32768
for q in /sys/class/net/eth0/queues/rx-*; do echo 4096 > "$q"/rps_flow_cnt; done

# Poprawa powinowactwa kolejek NVMe
echo 2 > /sys/block/nvme0n1/queue/rq_affinity
cat /sys/block/nvme0n1/queue/scheduler # "none" preferowane

„Uruchamiam “irqbalance" ze świadomością węzła lub ustawiam na Wyjątki dla przerwań hot-path. Rezultatem są bardziej stabilne opóźnienia, mniejsza liczba przeskoków IRQ między węzłami i wymierny wzrost liczby lokalnych wejść/wyjść.

Statyczne wiązanie vs. dynamiczne równoważenie - droga środka

Używam „taskset“ i cgroups, aby ustawić twarde reguły, gdy deterministyczne Opóźnienie liczy. Pozostawiam automatyczne równoważenie NUMA aktywne, gdy obciążenie się zmienia i potrzebuję adaptacyjnej bliskości. Często najlepiej sprawdza się mieszanka: twarde piny dla gorących ścieżek, bardziej otwarte granice dla pracy pomocniczej. Regularnie sprawdzam, czy migracje zauważalnie rosną, ponieważ sygnalizuje to słabe planowanie. Celem pozostaje wybranie lokalizacji danych i wątków w taki sposób, aby migracja była rzadka, ale możliwa.

NUMA w kontenerach i Kubernetes

Przynoszę pojemnik cpusets oraz Ogromne strony on line. Przypisuję pody/kontenery do węzła NUMA, przechowując spójne ilości procesora i pamięci. W orkiestracjach ustawiam zasady, które faworyzują przypisania do pojedynczego węzła, a tym samym szanują pierwsze dotknięcie.

  • Czas działania kontenera„-cpuset-cpus“ i „-cpuset-mems“ utrzymują zadania i pamięć razem; przypisują ogromne strony jako zasoby.
  • Topology/CPU ManagerŚcisłe lub preferowane przypisania zapewniają, że przydzielane są powiązane rdzenie i obszary pamięci.
  • Gwarantowana jakość usługStałe żądania/limity minimalizują redystrybucję przez program planujący.

Świadomie rozdzieliłem sidecary i procesy pomocnicze na inne rdzenie w ramach tego samego węzła, dzięki czemu ścieżka gorąca pozostaje niezakłócona, ale nie wchodzi w wyścig między węzłami.

Zrozumienie topologii procesorów: CCD/CCX, SNC i Cluster-on-Die

Obecne procesory serwerowe dzielą gniazda na Subdomeny z własnymi pamięciami podręcznymi i ścieżkami. Biorę to pod uwagę przy cięciu rdzeni/heapów:

  • AMD EPYCCCD/CCX i „NUMA na gniazdo“ (NPS=1/2/4) wpływają na to, jak dokładnie NUMA jest przycinana. Więcej węzłów (NPS=4) zwiększa lokalność, ale wymaga czystego przypinania.
  • IntelSub-NUMA Clustering (SNC2/4) dzieli LLC na klastry. Dobry dla obciążeń związanych z pamięcią, pod warunkiem, że system operacyjny i obciążenie są świadome węzłów.
  • Bliskość L3Wiążę wątki korzystające z tych samych hałd w tym samym klastrze L3, aby zaoszczędzić na ruchu spójności i przeskokach między klastrami.

Opcje te działają jak mnożnik: jeśli są używane prawidłowo, zwiększają Lokalizacja Ponadto - nieprawidłowo skonfigurowane, zwiększają fragmentację i ruch zdalny.

Wprowadzenie krok po kroku i plan wycofania

Nigdy nie wprowadzam tuningu NUMA typu „big bang“. Odporny Plan unika niespodzianek:

  1. Linia bazowaTopologia sprzętowa, opóźnienia P50/P95/P99, przepustowość, przechwytywanie szybkości numastat.
  2. HipotezaSformułuj konkretny cel (np. zdalny dostęp -30%, P99 -20%).
  3. Jeden krokZmień tylko jedną śrubę regulacyjną (np. cięcie VM, cpuset, polityka THP, interwały skanowania).
  4. KanarekPrzetestuj na 5-10% floty pod rzeczywistym obciążeniem, zachowaj gotowość do wycofania.
  5. WycenaPorównywanie zmierzonych wartości, definiowanie okien regresji, rejestrowanie efektów ubocznych.
  6. RolloutRozwijaj wałek po wałku, mierz ponownie po każdym wałku.
  7. KonserwacjaPonowne pomiary co kwartał (aktualizacje jądra, oprogramowania układowego i obciążenia zmieniają optymalne wartości).

Gwarantuje to, że ulepszenia są powtarzalne i można je cofnąć w ciągu kilku minut w przypadku błędu.

Najczęstsze błędy - i jak ich unikać

Typowym błędem jest aktywowanie przeplatania węzłów w BIOS-ie, co ukrywa topologię NUMA i Równoważenie trudniejsze. Równie niekorzystne: maszyny wirtualne z większą liczbą vCPU niż oferuje węzeł oraz nieczysto zarezerwowane ogromne strony. Niektórzy administratorzy spinają wszystko na sztywno, tracąc w ten sposób całą elastyczność, gdy zmienia się obciążenie. Inni polegają całkowicie na jądrze, choć twarde hotspoty wymagają jasnych reguł. Rejestruję serie pomiarów, wcześnie rozpoznaję wartości odstające i krok po kroku dostosowuję konfigurację i zasady.

  • THP „zawsze“ bez kontroli: nieplanowane kompaktowanie zakłóca opóźnienia. Wolę używać „madvise“ i specjalnie rezerwować duże strony.
  • vm.zone_reclaim_mode zbyt agresywny: Lokalne odzyskiwanie może przynieść więcej szkody niż pożytku w niewłaściwym momencie. Najpierw zmierzyć, potem wyostrzyć.
  • irqbalance blindNiekrytyczne IRQ przemieszczają się między węzłami. Ustawiam wyjątki lub stałe maski dla gorących ścieżek.
  • Mieszanka interleave + hard pinningSprzeczne polityki tworzą ping-pong. Opowiadam się za wyraźną linią dla każdej usługi.
  • Nieoczyszczone korpusyKontenery widzą węzeł, ale mapują pamięć do innych węzłów. Zawsze ustawiaj „cpuset.mems“ zgodnie z zestawem CPU.
  • Funkcje Sub-NUMA aktywowane, ale nieużywane: Więcej węzłów bez planowania zwiększa fragmentację. Włączanie tylko po testach.

Krótkie podsumowanie

NUMA Balancing Server łączy procesy i dane w ukierunkowany sposób, dzięki czemu dostęp lokalny jest częstszy i bardziej wydajny. Opóźnienia stają się krótsze. Przy odpowiednim rozmiarze maszyny wirtualnej, czystej konfiguracji BIOS-u i narzędziach takich jak numactl, tworzona jest przejrzysta topologia, którą wykorzystuje jądro. Wirtualne NUMA, ogromne strony i powinowactwa uzupełniają automatyczne równoważenie, zamiast je zastępować. Podłączanie urządzeń wejścia/wyjścia blisko węzłów i korzystanie z gorących ścieżek eliminuje kosztowny dostęp zdalny. W ten sposób sprzęt hostingowy skaluje się niezawodnie, a każda sekunda procesora dostarcza więcej mocy obliczeniowej. ładowność.

Artykuły bieżące