NUMA-medvetenhet och CPU-pinning för dedikerade servrar

16 min läsning - 16 juni 2026

hero section cover
Innehållsförteckning
  • NUMA-medvetenhet och CPU-pinning för dedikerade servrar
  • Hur NUMA fungerar på servrar med flera socklar
  • Inspektera NUMA-topologi på Linux
  • CPU-pinning och minnespolicyer
  • Välja strategi utifrån arbetsbelastning
  • BIOS- och kärninställningar att kontrollera
Dela

Hur man inspekterar NUMA-topologi och kopplar Linux-arbetsbelastningar till rätt kärnor och minne. Täcker numactl, taskset, systemd, BIOS-inställningar och arbetsbelastningsspecifika strategier.

NUMA-medvetenhet och CPU-pinning för dedikerade servrar

På alla servrar med flera socklar är det två olika frågor var en process körs och var dess minne finns, och att få dem ur synk är ett av de enklaste sätten att förlora prestanda. NUMA-medvetenhet och CPU-pinning är de två reglagen som löser detta. Det här inlägget handlar om hur NUMA fungerar, hur man inspekterar det på Linux och hur man pinnar arbetsbelastningar korrekt för databaser, AI-träning och latenskänsliga tjänster.

Hur NUMA fungerar på servrar med flera socklar

En NUMA-nod (Non-Uniform Memory Access) är en grupp av CPU-kärnor som är kopplade till ett lokalt RAM-minne via en dedikerad minneskontroller. På en server med två socklar har man vanligtvis två noder. Vilken kärna som helst kan läsa vilken adress som helst, men lokal åtkomst tar ungefär 80 ns medan en hop över sockeln via Intels UPI eller AMD:s Infinity Fabric tar cirka 130–150 ns. På större system med fler socklar kan den sämsta noden överstiga 250 ns.

Bandbredden följer samma mönster. Ett Sapphire Rapids-system med två socklar kan upprätthålla cirka 600 GB/s när kärnorna träffar det lokala minnet, men länken mellan socklarna är en bråkdel av det, så trafiken som passerar den blir snabbt en flaskhals. Processorer med många kärnor gör detta mer detaljerat: Intels Sub-NUMA Clustering (SNC) och AMD:s Nodes Per Socket (NPS) delar upp varje sockel i flera NUMA-domäner, så en ”tvåsockels”-enhet kan enkelt presentera fyra eller åtta noder för Linux.

Utan NUMA-medvetenhet kommer Linux-schemaläggaren glatt att migrera en tråd mellan socklar medan dess arbetsuppsättning stannar kvar på den ursprungliga noden. Varje efterföljande åtkomst blir en fjärråtkomst. Det synliga symptomet är hög CPU-användning med låg faktisk genomströmning, eftersom kärnorna lägger sin tid på att vänta på minnet. I/O-enheter förvärrar detta. En GPU eller NIC är ansluten till en specifik PCIe-rot, som tillhör en NUMA-nod. Om processen som matar den körs på den andra sockeln, korsar varje DMA-överföring interconnecten.

Inspektera NUMA-topologi på Linux

Fyra verktyg täcker nästan allt du behöver:

  • lscpu för en snabb sammanfattning av socklar och noder.
  • numactl --hardware för totalt minne per nod och matrisen över avstånd mellan noder.
  • numastat för hit/miss-räknare per process.
  • lstopo (från hwloc) för cachehierarki och PCIe-enhetslokalitet.

Börja med numactl --hardware. Den listar varje nod, kärnorna och minnet som tillhör den, samt avståndsmatrisen. Ett värde på 10 är lokalt, 20+ är avlägset. Om du ser en enda nod på en dator med flera socklar har ditt BIOS Node Interleaving aktiverat och döljer topologin; åtgärda det först (se nedan).

För en specifik process numastat -p <PID> visar var dess minne faktiskt är allokerat. Fyra räknare är viktiga:

  • numa_hit: minne allokerat på den avsedda noden. Du vill att detta ska vara högt.
  • numa_miss: den avsedda noden var full, allokeringen spreds till någon annanstans.
  • numa_foreign: en annan nod försökte allokera lokalt men kunde inte, vilket indikerar minnespress.
  • other_node: sidor allokerade på en annan nod än där processen körs. Höga värden här är ett klassiskt tecken på dålig pinning.

För GPU- eller NIC-arbetsbelastningar, kör lstopo-no-graphics och titta på vilken NUMA-nod varje PCIe-enhet är ansluten till. Om kärnorna som driver enheten finns på en annan nod är det det första du måste åtgärda.

CPU-pinning och minnespolicyer

CPU-pinning (eller CPU-affinitet) binder en process till specifika kärnor så att schemaläggaren inte kan migrera den. Det räcker inte i sig, eftersom Linux använder en first-touch-minnespolicy som standard: sidor tilldelas den nod som först skriver till dem. Om en tråd startar på fel nod innan den blir fastsatt, stannar dess minne där. Du måste kontrollera både placering och tilldelning tillsammans.

Tre verktyg täcker de vanligaste fallen:

VerktygKontrollerAnvänds för
tasksetEndast CPU-kärnorSnabb engångsbindning av en befintlig process
numactlCPU-kärnor och minneStarta arbetsbelastningar med strikt lokalitet
systemdCPU-kärnor och minne, beständigtTjänster som behöver låsas vid omstart

numactl stöder fyra minnespolicyer:

  • --membind=N: allokera endast på nod N, misslyckas om den är full.
  • --preferred=N: föredra nod N, fall tillbaka till andra vid behov.
  • --interleave=all: round-robin över noder för jämn bandbreddsfördelning.
  • --localalloc: allokera på den nod där den aktiva CPU:n finns.

Fästa en arbetsbelastning till en nod

Identifiera först vilka kärnor som tillhör din målnod:

numactl --hardware

Starta sedan applikationen bunden till den noden för både kärnor och minne:

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

För en redan körande process, justera CPU-affinitet med taskset:

taskset -cp 0-7 <PID>

För att den ska överleva en omstart, ställ in den i systemd-enheten:

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

Ladda om och starta om:

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

När du gör en manuell tilldelning, stäng av kärnans automatiska balansering så att den inte motverkar din placering:

sysctl -w kernel.numa_balancing=0

Lägg till den i /etc/sysctl.conf för att behålla inställningen. Verifiera sedan med numastat -p <PID> under några minuters verklig arbetsbelastning. Om other_node förblir nära noll, fungerar fästningen.

Välja strategi utifrån arbetsbelastning

Vilken policy som är rätt beror på om din arbetsbelastning gynnas mer av låg latens eller av sammanlagd bandbredd över alla noder.

ArbetsbelastningPolicyVarför
Databaser (PostgreSQL, MySQL, SQL Server)--cpunodebind + --membindStora delade buffertar, latenskänsliga sökvägar
Cache i minnet (Redis, Memcached)EnkelnodbindningAllt sker via RAM-åtkomst, fjärrfördröjning märks omedelbart
AI/ML-träning och inferensBindning till GPU:ns NUMA-nodUndviker tensoröverföringar som korsar PCIe-rötter
Analys (Spark, Elasticsearch)--interleave=allStora arbetsuppsättningar kräver bandbredd över alla noder
Latenskänsliga API:er, handelStrikt pin + IRQ-affinitetFörutsägbarhet är viktigare än toppgenomströmning
Nätverksintensivt (RoCEv2, InfiniBand)Pin till NIC:s NUMA-nod, dedikerade kärnor för IRQHåller avbrottshanteringen lokal och borta från apptrådar

Specifikt för GPU-arbetsbelastningar, kör lstopo för att ta reda på vilken NUMA-nod GPU:n sitter på, och starta sedan tränings- eller inferensprocessen med numactl --cpunodebind=N --membind=N för samma N. Detta är en av de enklaste förbättringarna på en GPU-server med flera socklar, eftersom standardplaceringen i schemaläggaren ofta är fel.

För HPC- och MPI-arbetsbelastningar som spänner över båda socklarna, fäst varje rang till en enda nod med localalloc istället för att interfoliera allt. Varje rank får lokalt minne, och parallelliteten sker på ranknivå.

En praktisk anmärkning: om du kopplar till en enda nod, lämna 2–4 GB ledigt utrymme på den. En nod som körs nära full kapacitet utlöser återvinning, vilket kostar dig den latens du försökte spara.

BIOS- och kärninställningar att kontrollera

Verktygets resultat är endast så exakt som den topologi som firmware visar. Några inställningar att bekräfta:

  • Node Interleaving: inaktivera det. När det är aktiverat presenterar BIOS allt minne som en enda platt pool och döljer NUMA helt från operativsystemet. numactl --hardware Visar en nod på en dator med flera socklar om så är fallet.
  • Sub-NUMA Clustering (Intel) eller Nodes Per Socket (AMD): aktivera på processorer med många kärnor när du vill ha finare lokalitet. Bekräftas i lscpu efter omstart.
  • vm.zone_reclaim_mode: ställ in på 0 för de flesta produktionsservrar. Ett värde som inte är noll återvinner lokalt minne aggressivt istället för att allokera på distans, vilket kan fördriva användbar sidcache.
  • kernel.numa_balancing: lämna på för allmänna arbetsbelastningar, stäng av när du manuellt fäster. Den automatiska balanseraren kommer att migrera sidor och trådar på sätt som strider mot din policy.

Om du kör NUMA-inställningar på bare metal där du kontrollerar BIOS, kärnparametrar och IRQ-affinitet kan du tillämpa allt ovanstående utan att behöva kringgå hypervisorabstraktioner. Det är den främsta anledningen till att detta slags arbete är enklare på dedikerad hårdvara än i moln-VM:er.

För dedikerade servrar med flera socklar och fullständig root-åtkomst, se FDC:s dedikerade servrar.

Blogg

Utvalda denna vecka

Fler artiklar
Tuned Profiles för optimering av arbetsbelastningen för Linux-server

Tuned Profiles för optimering av arbetsbelastningen för Linux-server

Hur man väljer, tillämpar och anpassar tunade profiler för GPU-, databas- och Linux-servrar med hög bandbredd, med exempel och Ansible-driftsättningstips.

16 min läsning - 9 juni 2026

Linux OOM Killer Tuning för VPS: En praktisk guide

12 min läsning - 8 juni 2026

Fler artiklar
background image

Har du frågor eller behöver du en anpassad lösning?

icon

Flexibla alternativ

icon

Global räckvidd

icon

Omedelbar driftsättning

icon

Flexibla alternativ

icon

Global räckvidd

icon

Omedelbar driftsättning