Consapevolezza NUMA e pinning della CPU per i server dedicati
16 min di lettura - 16 giugno 2026

Come ispezionare la topologia NUMA e assegnare i carichi di lavoro Linux ai core e alla memoria corretti. Tratta numactl, taskset, systemd, impostazioni del BIOS e strategie specifiche per i carichi di lavoro.
Consapevolezza NUMA e pinning della CPU per i server dedicati
Su qualsiasi server multi-socket, dove viene eseguito un processo e dove risiede la sua memoria sono due questioni diverse, e farle andare fuori sincrono è uno dei modi più semplici per compromettere le prestazioni. La consapevolezza NUMA e il pinning della CPU sono le due leve che risolvono questo problema. Questo post spiega come funziona NUMA, come ispezionarlo su Linux e come assegnare correttamente i carichi di lavoro per database, addestramento AI e servizi sensibili alla latenza.
Come funziona NUMA sui server multi-socket
Un nodo NUMA (Non-Uniform Memory Access) è un gruppo di core CPU collegati a un blocco locale di RAM tramite un controller di memoria dedicato. Su un server a due socket di solito ci sono due nodi. Qualsiasi core può leggere qualsiasi indirizzo, ma l'accesso locale è di circa 80 ns, mentre un salto tra socket tramite l'UPI di Intel o l'Infinity Fabric di AMD è di circa 130–150 ns. Su sistemi più grandi con più socket, il nodo nel caso peggiore può superare i 250 ns.
La larghezza di banda segue lo stesso andamento. Un sistema Sapphire Rapids a due socket può sostenere circa 600 GB/s quando i core accedono alla memoria locale, ma il collegamento tra i socket è una frazione di questo valore, quindi il traffico che lo attraversa crea rapidamente un collo di bottiglia. I processori ad alto numero di core rendono questo aspetto più granulare: il Sub-NUMA Clustering (SNC) di Intel e il Nodes Per Socket (NPS) di AMD dividono ogni socket in più domini NUMA, così un sistema a "due socket" può facilmente presentare quattro o otto nodi a Linux.
Senza il supporto NUMA, lo scheduler di Linux migrerà tranquillamente un thread tra i socket mentre il suo working set rimane sul nodo originale. Ogni accesso successivo diventa remoto. Il sintomo visibile è un elevato utilizzo della CPU con un throughput effettivo basso, perché i core passano il loro tempo in attesa della memoria. I dispositivi I/O peggiorano la situazione. Una GPU o una scheda di rete è collegata a una radice PCIe specifica, che appartiene a un nodo NUMA. Se il processo che la alimenta viene eseguito sull'altro socket, ogni trasferimento DMA attraversa l'interconnessione.
Analisi della topologia NUMA su Linux
Quattro strumenti coprono quasi tutto ciò di cui avete bisogno:
lscpuper un riepilogo rapido dei socket e dei nodi.numactl --hardwareper i totali di memoria dei nodi e la matrice delle distanze tra i nodi.numastatper i contatori di hit/miss per processo.lstopo(da hwloc) per la gerarchia della cache e la località dei dispositivi PCIe.
Inizia con numactl --hardware. Elenca ogni nodo, i core e la memoria ad esso appartenenti, e la matrice delle distanze. Un valore di 10 è locale, 20+ è remoto. Se vedete un singolo nodo su un sistema multi-socket, il vostro BIOS ha abilitato il Node Interleaving e sta nascondendo la topologia; risolvete prima questo problema (vedi sotto).
Per un processo specifico, numastat -p <PID> analizza dove è effettivamente allocata la sua memoria. Quattro contatori sono importanti:
numa_hit: memoria allocata sul nodo previsto. È auspicabile che questo valore sia alto.numa_miss: il nodo previsto era pieno, l'allocazione è stata trasferita altrove.numa_foreign: un altro nodo ha tentato di allocare localmente senza riuscirci, il che indica una pressione sulla memoria.other_node: pagine allocate su un nodo diverso da quello su cui è in esecuzione il processo. Valori elevati qui sono il classico segno di un pinning inadeguato.
Per i carichi di lavoro GPU o NIC, esegui lstopo-no-graphics e controlla a quale nodo NUMA è collegato ciascun dispositivo PCIe. Se i core che gestiscono il dispositivo si trovano sull'altro nodo, questa è la prima cosa da risolvere.
CPU pinning e politiche di memoria
Il pinning della CPU (o affinità della CPU) associa un processo a core specifici in modo che lo scheduler non possa migrarlo. Di per sé ciò non è sufficiente, poiché Linux utilizza per impostazione predefinita una politica di memoria "first-touch": le pagine vengono allocate sul primo nodo che scrive su di esse. Se un thread si avvia sul nodo sbagliato prima di essere pinato, la sua memoria rimane lì. È necessario controllare sia il posizionamento che l'allocazione insieme.
Tre strumenti coprono i casi più comuni:
| Strumento | Controlli | Utilizzo |
|---|---|---|
taskset | Solo core CPU | Assegnazione rapida e una tantum di un processo esistente |
numactl | Core CPU e memoria | Avvio di carichi di lavoro con località rigorosa |
| systemd | Core CPU e memoria, persistente | Servizi che richiedono il pinning tra i riavvii |
numactl supporta quattro politiche di memoria:
--membind=N: allocare solo sul nodo N, fallire se pieno.--preferred=N: preferisce il nodo N, ricorre agli altri se necessario.--interleave=all: round-robin tra i nodi per una distribuzione uniforme della larghezza di banda.--localalloc: allocazione sul nodo su cui si trova la CPU in esecuzione.
Fissare un carico di lavoro su un nodo
Per prima cosa, identifica quali core appartengono al tuo nodo di destinazione:
numactl --hardwareQuindi avviare l'applicazione associata a quel nodo sia per i core che per la memoria:
numactl --cpunodebind=0 --membind=0 ./your_applicationPer un processo già in esecuzione, regolare l'affinità della CPU con taskset:
taskset -cp 0-7 <PID>Per far sì che sopravviva a un riavvio, impostalo nell'unità systemd:
[Service]
CPUAffinity=0-7
NUMAPolicy=bind
NUMAMask=0Ricaricare e riavviare:
sudo systemctl daemon-reload && sudo systemctl restart <service>Quando esegui l'assegnazione manuale, disattiva il bilanciatore automatico del kernel in modo che non interferisca con il tuo posizionamento:
sysctl -w kernel.numa_balancing=0Aggiungilo a /etc/sysctl.conf per renderlo permanente. Quindi verificare con numastat -p <PID> per un paio di minuti di carico di lavoro reale. Se other_node rimane vicino allo zero, il pinning sta funzionando.
Scegliere una strategia in base al carico di lavoro
La politica giusta dipende dal fatto che il vostro carico di lavoro tragga maggior beneficio da una bassa latenza o dalla larghezza di banda aggregata su tutti i nodi.
| Carico di lavoro | Politica | Motivo |
|---|---|---|
| Database (PostgreSQL, MySQL, SQL Server) | --cpunodebind + --membind | Buffer condivisi di grandi dimensioni, percorsi di query sensibili alla latenza |
| Cache in memoria (Redis, Memcached) | Bind a nodo singolo | Tutto avviene tramite accesso alla RAM, la latenza remota si manifesta immediatamente |
| Addestramento e inferenza AI/ML | Bind al nodo NUMA della GPU | Evita i trasferimenti di tensori che attraversano le radici PCIe |
| Analisi (Spark, Elasticsearch) | --interleave=all | Un working set di grandi dimensioni richiede larghezza di banda su tutti i nodi |
| API sensibili alla latenza, trading | Affinità pin + IRQ rigorosa | La prevedibilità è più importante del throughput di picco |
| Intenso utilizzo della rete (RoCEv2, InfiniBand) | Pin al nodo NUMA della scheda di rete, core dedicati per gli IRQ | Mantiene l'elaborazione degli interrupt a livello locale e fuori dal percorso dei thread delle app |
Per i carichi di lavoro GPU in particolare, eseguire lstopo per individuare su quale nodo NUMA si trova la GPU, quindi avviare il processo di addestramento o di inferenza con numactl --cpunodebind=N --membind=N per quello stesso N. Questo è uno dei vantaggi più facili da ottenere su un server GPU multi-socket, poiché il posizionamento predefinito dello scheduler è spesso errato.
Per i carichi di lavoro HPC e MPI che si estendono su entrambi i socket, fissare ogni rank a un singolo nodo con localalloc anziché intercalare tutto. Ogni rank ottiene memoria locale e il parallelismo avviene a livello di rank.
Una nota pratica: se si associa un singolo nodo, lasciare 2–4 GB di margine su di esso. Un nodo che opera quasi al massimo della capacità innesca il recupero della memoria, il che comporta una latenza che si stava cercando di evitare.
Impostazioni del BIOS e del kernel da verificare
L'accuratezza dei risultati dello strumento dipende dalla topologia esposta dal firmware. Alcune impostazioni da verificare:
- Interleaving dei nodi: disabilitarlo. Quando è abilitato, il BIOS presenta tutta la memoria come un unico pool piatto e nasconde completamente il NUMA al sistema operativo.
numactl --hardwareIn questo caso, verrà visualizzato un solo nodo su un sistema multi-socket. - Clustering Sub-NUMA (Intel) o Nodi per Socket (AMD): abilitare su processori con molti core quando si desidera una localizzazione più precisa. Verificare
lscpudopo il riavvio. vm.zone_reclaim_mode: impostare su 0 per la maggior parte dei server di produzione. Un valore diverso da zero recupera in modo aggressivo la memoria locale anziché allocare in remoto, il che può espellere la cache di pagina utile.kernel.numa_balancing: lasciarlo attivo per carichi di lavoro generici, disattivarlo quando si esegue il pinning manualmente. Il bilanciatore automatico migrerà pagine e thread in modi che entrano in conflitto con la vostra politica.
Se si esegue l'ottimizzazione NUMA su bare metal dove si controllano il BIOS, i parametri del kernel e l'affinità IRQ, è possibile applicare tutto quanto sopra senza aggirare le astrazioni dell'hypervisor. Questo è il motivo principale per cui questo tipo di lavoro è più facile su hardware dedicato che nelle VM cloud.
Per i server dedicati multi-socket con accesso root completo, consultare i server dedicati di FDC.

Profili ottimizzati per l'ottimizzazione del carico di lavoro dei server Linux
Come scegliere, applicare e personalizzare i profili sintonizzati per GPU, database e server Linux a elevata larghezza di banda, con esempi e suggerimenti per l'implementazione di Ansible.
16 min di lettura - 9 giugno 2026
Messa a punto di Linux OOM Killer per VPS: una guida pratica
12 min di lettura - 8 giugno 2026

Avete domande o avete bisogno di una soluzione personalizzata?
Opzioni flessibili
Portata globale
Distribuzione immediata
Opzioni flessibili
Portata globale
Distribuzione immediata