Capitolo 4. CPU
CPU è l'acronimo di central processing unit, tale nome non risulta essere totalmente corretto per la maggior parte dei sistemi poichè centrale implica singolo, e numerosi sistemi moderni possiedono più di una unità di processazione, o core. Fisicamente le CPU sono contenute in un pacchetto assegnato ad una scheda madre in un socket. Ogni socket presenta diverse connessioni: ad altri socket della CPU, controllori della memoria, controllori degli interrupt ed altri dispositivi periferici. Un socket per un sistema operativo è un raggruppamento logico di CPU e risorse associate. Questo concetto è importante in numerose discussioni sulla ottimizzazione della CPU.
Red Hat Enterprise Linux detiene un certo numero di informazioni sulle statistiche relative agli eventi della CPU del sistema; queste statistiche sono utili nella pianificazione di una strategia per il miglioramento delle prestazioni di una CPU. Sezione 4.1.2, «Ottimizzazione delle prestazioni della CPU» approfondisce alcune statistiche utili, dove trovarle e come analizzarle.
Tipoligia
I computer più vecchi presentavano un numero di CPU per sistema più basso, permettendo così di implementare una architettura Symmetric Multi-Processor (SMP). Ogni CPU nel sistema aveva un accesso simile (o simmetrico) per la memoria disponibile. Col tempo il conteggio-per-socket della CPU è aumentato al punto che il tentativo di dare un accesso simmetrico a tutta la RAM nel sistema, è diventato un processo molto costoso. In tempi più recenti i sistemi con un conteggio CPU molto elevato implementano una architettura Non-Uniform Memory Access (NUMA) e non SMP.
I processori AMD da tempo presentano questo tipo di architettura con le proprie interconnessioni Hyper Transport (HT), mentre Intel ha iniziato ad implementare NUMA nei propri Quick Path Interconnect (QPI). NUMA e SMP sono regolati in modo differente poichè è necessario considerare le tipologie del sistema durante l'assegnazione delle risorse per una applicazione.
Thread
Nei sistemi operativi di Linux l'unità di esecuzione è conosciuta come thread. I thread hanno un contesto dei registri, una stack e un segmento del codice da eseguire su una CPU. È compito del sistema operativo (OS) programmare i thread sulle CPU disponibili.
Il sistema operativo massimizza l'uso della CPU attraverso un bilanciamento del carico dei thread su tutti i core disponibili. Poichè il compito principale del sistema operativo è quello di mantenere occupata la CPU, esso potrebbe non essere il più idoneo in relazione alla gestione delle prestazioni dell'applicazione. Spostando un thread dell'applicazione su una CPU di un altro socket, si potranno peggiorare le prestazioni più di quanto si possa verificare in relazione all'attesa di una CPU corrente, poichè le operazioni di accesso della memoria potrebbero rallentare drasticamente su tutti i socket. Per applicazioni ad elevate prestazioni è più idoneo determinare la posizione dei thread. Sezione 4.2, «Programmazione della CPU» contienene le informazioni necessarie su come assegnare le memoria e la CPU nel modo più opportuno per una esecuzione migliore dei thread dell'applicazione.
interrupt
Uno degli eventi del sistema meno ovvi (ma importante) che possono interessare negativamente le prestazioni di una applicazione, è un interrupt (conosciuta in Linux come IRQ). Questi eventi sono gestiti dal sistema operativo e vengono usati dalle periferiche per segnalare l'arrivo di dati o il completamento di una operazione, come ad esempio le scritture della rete o un evento del timer.
La gestione di un interrupt da parte di un sistema operativo o una CPU che esegue un codice dell'applicazione, non interessa la funzionalità dell'applicazione, ma al contrario potrebbe riguardare le sue prestazioni. Questo capitolo affronta alcuni argomenti su come evitare un impatto negativo sulle prestazioni di una applicazione in presenza di interrupt.
4.1. Tipologia della CPU
4.1.1. Tipologia NUMA e CPU
I primi processori erano di tipo uniprocessor, quindi il sistema era provvisto di una sola CPU. L'esecuzione di processi in parallelo era resa possibile tramite l'uso di un sistema operativo il quale smistava rapidamente la CPU da un thread di esecuzione (processo) ad un altro. Durante gli studi per migliorare le prestazioni, i designer notarono che aumentando la velocità dell'orologio per eseguire più velocemente le istruzioni, le prestazioni miglioravano ma solo fino ad un certo punto (generalmente limitazioni nella creazione di una frequenza dell'orologio stabile con la tecnologia corrente). Per migliorare le prestazioni è stata aggiunta una seconda CPU al sistema, permettendo così l'esecuzione parallela di due flussi. Questa tendenza di aggiungere processori è continuata con gli anni.
Numerosi sistemi con processori multipli venivano creati in modo che ogni CPU era in possesso dello stesso percorso logico per ogni posizione della memoria (generalmente un bus parallelo). In questo modo ogni CPU era in grado di accedere a qualsiasi posizione della memoria, usando la stessa quantità di tempo di qualsiasi altra CPU nel sistema. Questo tipo di architettura è conosciuta come sistema Symmetric Multi-Processor (SMP). SMP è ideale con un numero ristretto di CPU, ma superando un determinato numero (8 o 16), il numero di tracce parallele necessarie per un accesso uguale alla memoria utilizza una quantità di spazio troppo elevata, lasciando così meno spazio alla periferiche.
Due nuovi concetti uniti tra loro permettono di avere un numero più alto di CPU in un sistema:
- Bus seriali
- Tipologie NUMA
Un bus seriale è un percorso di comunicazione a linea singola con una velocità elevata dell'orologio in grado di trasferire dati in gruppi "o burst" di pacchetti con caratteristiche simili. In passato gli sviluppatori hardware hanno implementato i bus seriali come interconnessioni ad elevata velocità tra CPU, e tra i controllori della memoria e le CPU e altre periferiche. Questa impostazione permetteva l'uso di una traccia al posto di 32 e 34 tracce sulla scheda di ogni CPU per il sottosistema della memoria, riducendo così la quantità di spazio necessario sulla scheda.
Contemporaneamente gli sviluppatori hardware implementavano un numero sempre maggiore di transistor nello stesso spazio, riducendo così le dimensioni die. Al posto di inserire singole CPU direttamente sulla scheda principale, essi iniziarono ad inserirle in un pacchetto del processore utilizzandole così come processori multi-core. Successivamente al posto di fornire un accesso uniforme per la memoria da ogni pacchetto del processore, gli sviluppatori hanno iniziato ad implementare una strategia Non-Uniform Memory Access (NUMA), dove ogni combinazione pacchetto/socket presentava una o più aree specifiche della memoria per un accesso ad elevata velocità. Ogni socket possedeva altresì una interconnessione per altri socket per un accesso più lento alla memoria.
Per un esempio di implementazione NUMA semplice supponiamo di avere una scheda madre con due socket, dove ogni socket è stato popolato con un pacchetto quad-core. Ciò significa che il numero totale di CPU nel sistema è otto; quattro per ongi socket. Ogni socket presenta altresì un insieme di memoria assegnata con quattro gigabyte di RAM per un totale di otto gigabyte. Per questo esempio le CPU 0-3 sono posizionate nel socket 0, e le CPU 4-7 sono nel socket 1. Ogni socket in questo esempio corrisponde anche ad un nodo NUMA.
Per accedere alla memoria dall'insieme 0 potranno essere necessari tre cicli di orologio alla CPU 0: un ciclio per presentare l'indirizzo al controller della memoria, un ciclio per impostare l'accesso per la posizione della memoria e un ciclio per leggere o scrivere sulla posizione. Tuttavia potrebbe richiedere alla CPU 4 fino a sei cicli per accedere alla memoria dalla stessa posizione, poichè posizionata su un secondo socket, essa avrà la necessità di superare due controllori della memoria: il controllore della memoria locale sul socket 1 e successivamente il controllore della memoria remota sul socket 0. Se la memoria viene contesa (e cioè se più di una CPU cerca di accedere alla stessa posizione contemporaneamente), i controllori avranno la necessità di regolare e serializzare l'accesso alla memoria, richiedendo così un tempo maggiore. Tale processo viene sommato alla consistenza della cache (assicurare che le cache delle CPU locali contangano dati uniformi per la stessa posizione della memoria) e complica maggiormente il processo.
Gli ultimissimi processori "high-end" di Intel (Xeon) e AMD (Opteron) presentano un NUMA. I processori AMD utilizzano una interconnessione conosciuta come HyperTransport o HT, mentre Intell utilizza una QuickPath Interconnect o QPI. Le interconnessioni differiscono dal tipo di collegamento fisico, memoria o dispositivi periferici, ma in effetti essi sono interruttori che permettono un accesso trasparente, da un dispositivo, ad un dispositivo connesso. In questo caso il termine trasparente si riferisce al fatto che non è presente alcuna API di programmazione speciale necessaria per l'utilizzo dell'interconnessione, non una opzione "senza alcun costo".
A causa della varietà di tipologie delle architetture di un sistema, non è pratico caratterizzare in modo specifico la penalità imposta da un accesso della memoria non-locale. Possiamo dire che ogni segmento "hop" in una interconnessione impone sempre una piccola penalità sulle prestazioni, per questo motivo riferire ad una posizione distante due interconnessioni dalla CPU corrente, impone un minimo di 2N + tempo del ciclo della memoria per l'accesso, dove N è la penalità per segmento "hop".
Data la suddetta penalità, le applicazioni sensibili alle prestazioni dovrebbero evitare un accesso alla memoria remota in un sistema con una tipologia NUMA. Impostare l'applicazione in modo che essa si trovi in un nodo specifico, ed in grado di assegnare memoria dal nodo in questione.
Per fare questo è necessario essere a conoscenza di:
- Cos'è la tipologia del sistema?
- Dov'è l'applicazione attualmente eseguita?
- Dov'è l'insieme di memoria più vicino?
4.1.2. Ottimizzazione delle prestazioni della CPU
Consultare questa sezione per capire come eseguire una ottimizzazione delle prestazioni della CPU e per una introduzione agli strumenti usati a tale scopo.
NUMA è stato originariamente usato per collegare un processore ad insiemi multipli di memoria. Con il miglioramento dei processi e la riduzione delle dimensioni dei circuiti integrati, è diventato possibile includere numerose CPU core in un pacchetto. Le suddette CPU core sono state clusterizzate in modo da avere un tempo d'accesso uguale ad un insieme della memoria locale, rendendo possibile così una condivisione della cache tra i core; tuttavia ogni 'segmento' presente in una interconnessione tra core, memoria e cache presenta una piccola penalità.
L'esempio di sistema presente in Figura 4.1, «Accesso alla memoria locale e remota con NUMA» riporta due nodi NUMA. Ogni nodi ha quattro CPU, un insieme di memoria ed un controller. Ogni CPU in un nodo ha un accesso diretto all'insieme della memoria su quel nodo. Seguendo le freccette sul Nodo 1 le fasi risultano essere:
- Una CPU (qualsiasi tra 0-3) presenta un indirizzo per il controller della memoria locale.
- Il controller della memoria imposta un accesso per l'indirizzo.
- La CPU esegue operazioni di lettura o scrittura sull'indirizzo della memoria.
Figura 4.1. Accesso alla memoria locale e remota con NUMA
Tuttavia se una CPU di un nodo ha bisogno di accedere ad un codice all'interno di un insieme di memoria di un nodo NUMA diverso, il percorso da seguire sarà meno diretto:
- Una CPU (qualsiasi tra 0-3) presenta un indirizzo della memoria remota per il controller della memoria locale.
- La richiesta di una CPU per l'indirizzo della memoria locale viene passato ad un controller della memoria remota, locale al nodo che contiene quell'indirizzo.
- Il controller della memoria remota imposta un accesso per l'indirizzo della memoria remota.
- La CPU esegue operazioni di lettura o scrittura sull'indirizzo della memoria remota.
Ogni azione deve passare attraverso numerosi controller di memoria, quindi l'accesso può richiedere il doppio del tempo se si cerca di accedere ad indirizzi di memorie remote. Quindi per mantenere un livello di prestazione desiderato in un sistema multi-core, assicurarsi che le informazioni siano passate il più efficientemente possibile usando il percorso più veloce o più corto.
Per configurare una applicazione per una prestazione della CPU ottimale è necessario sapere:
- la tipologia del sistema (collegamento dei componenti)
- il core sul quale viene eseguita l'applicazione, e
- la posizione dell'insieme di memoria più vicino.
Red Hat Enterprise Linux 6 rende disponibili alcuni strumenti per poter eseguire una ottimizzazione del sistema in base alle informazioni disponibili. Le seguenti sezioni forniscono una panoramica sugli strumenti utili per una ottimizzazione delle prestazioni della CPU.
4.1.2.1. Impostazione affinità della CPU con taskset
taskset ripristina ed imposta l'affinità della CPU di un processo in esecuzione (in base all'ID del processo). Può essere usato anche per lanciare un processo con una affinità della CPU conosciuta, associando il processo specifico ad una CPU o insieme di CPU. Tuttavia taskset non è in grado di garantire una assegnazione della memoria locale. Per benefici aggiuntivi dovuti all'assegnazione della memoria locale è consigliato usare numactl al posto di taskset; per maggiori informazioni consultare Sezione 4.1.2.2, «Controllo politica di NUMA con numactl».
L'affinità della CPU è rappresentata con un bitmask. Il bit con un ordine più basso corrisponde alla prima CPU logica, mentre il bit con l'ordine più alto corrisponde all'ultima CPU logica. Queste maschere vengono generalmente riportate in esadecimali, quindi
0x00000001
rappresenta il processore 0 e 0x00000003
rappresenta i processori 0 e 1.
Per impostare una affinità della CPU di un processo in esecuzione eseguire il seguente comando, sostituendo mask con la maschera del processore o processori con i quali desiderate associare il processo, e pid con l'ID del processo al quale desiderate modificare l'affinità.
# taskset -p mask pid
Per lanciare un processo con una data affinità eseguire il seguente comando, sostituendo mask con la maschera del processore o processori con i quali desiderate associare il processo, e program con il processo, le opzioni e gli argomenti del programma da eseguire.
# taskset mask -- program
Al posto di specificare i processori attraverso un bitmask sarà possibile specificare l'opzione
-c
per fornire un elenco delimitato da virgole di processori separati, o di una gamma di processori:
# taskset -c 0,5,7-9 -- myprogram
Maggiori informazioni su taskset sono disponibili attraverso la pagina man:
man taskset
.
4.1.2.2. Controllo politica di NUMA con numactl
numactl
esegue i processi con una programmazione specifica o utilizzando una politica di posizionamento della memoria. La politica selezionata viene impostata per quel processo e per tutti i suoi processi figlio. numactl
è in grado altresì di impostare una politica persistente per segmenti di memoria condivisi o file, e l'affinità della CPU e della memoria di un processo. Per determinare la tipologia del sistema esso utilizza il file system /sys
.
Il file system
/sys
contiene informazioni utili sul collegamento delle CPU, memoria e dispositivi periferici con le interconnessioni NUMA. In modo specifico la directory /sys/devices/system/cpu
contiene le informazioni sul collegamento delle CPU di un sistema. La directory /sys/devices/system/node
contiene le informazioni sui nodi NUMA presenti nel sistema e sulle distanze che intercorrono tra i nodi.
In un sistema NUMA, maggiore è la distanza presente tra un processore ed un insieme di memoria e più lenta è la velocità d'accesso del processore per l'insieme in questione. A tale scopo configurare applicazioni sensibili alle prestazioni per poter assegnare memoria dall'insieme di memoria più vicino.
È consigliato anche configurare applicazioni "performance-sensitive" per eseguire un certo numero di core, in particolare nel caso di applicazioni multi-thread. Poichè le cache del primo livello sono generalmente piccole in presenza di thread multipli in esecuzione in un singolo core, ogni thread potrebbe espellere i dati memorizzati in cache usati da un thread precedente. Quando un sistema operativo cerca di eseguire un certo numero di compiti tra i thread, i quali a loro volta continuano ad espellere i dati usati dai thread precedenti, una grossa quantità di tempo di esecuzione verrà usata per la sostituzione della linea di cache. Questo problema si chiama cache thrashing. Per questo motivo è consigliato associare una applicazione multi-thread ad un nodo e non ad un singolo core, poichè così facendo permetterete ai thread di condividere le linee in cache su livelli multipli (prima, seconda e cache dell'ultimo livello) e minimizzerete la necessità di operazioni per il riempimento della cache. Tuttavia l'associazione di una applicazione ad un core singolo può garantire un buon livello di prestazioni se tutti i thread accedono agli stessi dati presenti in cache.
numactl permette di associare una applicazione ad un nodo NUMA o core particolare, e di assegnare la memoria associata con un core o insieme di core all'applicazione in questione. Alcune opzioni utili disponibili con numactl sono:
--show
- Mostra le impostazioni della politica NUMA del processo corrente. Questo parametro non ha bisogno di parametri aggiuntivi e può essere usato nel modo seguente:
numactl --show
. --hardware
- Mostra un inventario dei nodi disponibili sul sistema.
--membind
- Assegna solo la memoria dai nodi specificati. Se in uso, il processo di assegnazione fallirà se la memoria sui nodi in questione non è sufficiente. Il formato per questo parametro è
numactl --membind=nodes program
, dove nodes è l'elenco dei nodi usati per assegnare la memoria e program è il programma usato per i requisiti di memoria che i nodi dovranno assegnare. È possibile indicare i numeri dei nodi con un elenco separato da virgole, una gamma o una combinazione dei due. Maggiori informazioni sono disponibili sulle pagine man di numactl:man numactl
. --cpunodebind
- Esegue solo un comando (e i processi figli relativi) sulle CPU che appartengono ai nodi specificati. Il formato di questo parametro è il seguente
numactl --cpunodebind=nodes program
, dove nodes è l'elenco dei nodi specificati usati per indicare le CPU per l'assegnazione dei programmi desiderati (program). È possibile indicare i numeri dei nodi con un elenco separato da virgole, una gamma o una combinazione dei due. Maggiori informazioni sono disponibili sulle pagine man di numactl:man numactl
. --physcpubind
- Esegue solo un comando (e i processi figli relativi) sulle CPU specificate. Il formato di questo parametro è il seguente
numactl --physcpubind=cpu program
, dove cpu è l'elenco delimitato da virgole dei numeri delle CPU fisiche, come riportato nei campi dei processori di/proc/cpuinfo
, e program è il programma da eseguire solo sulle CPU in questione. È possibile specificare le CPU in relazione alcpuset
corrente. Consultare le pagine man di numactl per maggiori informazioni:man numactl
. --localalloc
- Specifica che la memoria deve sempre essere assegnata sul nodo corrente.
--preferred
- Quando possibile assegna la memoria sul nodo specificato, In caso contrario usare altri nodi. Questa opzione accetta solo il numero di un singolo nodo, come ad esempio:
numactl --preferred=node
. Consultare la pagina man di numactl per maggiori informazioni:man numactl
.
La libreria libnuma inclusa nel pacchetto numactl offre una interfaccia di programmazione semplice per la politica NUMA supportata dal kernel. Utile per una regolazione più dettagliata rispetto all'utilità numactl. Per maggiori informazioni consultare la pagina man relativa:
man numa(3)
.
4.1.3. numastat
Importante
In precedenza numastat era uno script Perl scritto da Andi Kleen, mentre ora è stato riscritto per Red Hat Enterprise Linux 6.4.
Anche se il comando predefinito (
numastat
senza alcuna opzione o parametri) mantiene una compatibilità con la versione precedente, l'uso di opzioni o parametri con questo comando modificherà sensibilmente il formato e il contenuto dell'output.
numastat mostra le informazioni relative alla memoria (ad esempio i successi ed i fallimenti della memoria) per processi e sistemi operativi in base al per-NUMA-nodo. Per impostazione predefinita l'esecuzione di
numastat
mostra il numero di pagine di memoria occupate dalle seguenti categorie di eventi per ogni nodo.
Prestazioni ottimali della CPU vengono indicate da valori
numa_miss
e numa_foreign
bassi.
Questa versione aggiornata di numastat indica anche se la memoria del processo viene condivisa dall'intero sistema o se risulta centralizzata su nodi specifici che utilizzano numactl.
Eseguire un riferimento incrociato dell'output numastat con l'output top per-CPU, per verificare che i thread del processo siano in esecuzione sugli stessi nodi ai quali è stata assegnata la memoria.
Categorie di verifica predefinite
- numa_hit
- Numero di tentativi di assegnazione riusciti per il nodo.
- numa_miss
- Numero di tentativi di assegnazione ad un altro nodo allocati a questo nodo a causa di una quantità di memoria limitata sul nodo desiderato. Ogni evento
numa_miss
ha un eventonuma_foreign
corrispondente su un altro nodo. - numa_foreign
- Numero di assegnazioni intese inizialmente per questo nodo allocate invece ad un altro nodo. Ogni evento
numa_foreign
ha un eventonuma_miss
su un altro nodo. - interleave_hit
- Numero di tentativi di assegnazione della politica interleave per questo nodo che hanno avuto successo.
- local_node
- Numero di volte che un processo sul nodo ha assegnato con successo la memoria a questo nodo.
- other_node
- Numero di volte che un processo su un altro nodo ha assegnato la memoria a questo nodo.
L'uso delle seguenti opzioni modifica le unità visualizzate in megabyte di memoria (approssimate a due cifre decimali), e modifica altri comportamenti numastat specifici come di seguito riportato.
-c
- Riduce orizzontalmente la tabella delle informazioni. Utile su sistemi con un numero molto grande di nodi NUMA, ma lo spazio tra colonne e la loro larghezza può essere imprevedibile. Usando questa opzione la quantità di memoria viene approssimata al megabyte per vicino.
-m
- Mostra le informazioni sull'uso della memoria dell'intero sistema in base al nodo. Simile alle informazioni disponibili in
/proc/meminfo
. -n
- Mostra le stesse informazioni del comando originale
numastat
(numa_hit, numa_miss, numa_foreign, interleave_hit, local_node, and other_node), con un formato aggiornato, usando i megabyte come unità di misura. -p pattern
- Mostra le informazioni della memoria per-node per il pattern specificato. Se il valore di pattern è composto da cifre, numastat assume che si tratti di un identificatore di un processo numerico. In caso contrario numastat ricerca le righe del comando del processo per il pattern specificato.Gli argomenti della linea di comando inseriti dopo il valore dell'opzione
-p
vengono considerati pattern aggiuntivi da filtrare. Pattern aggiuntivi aumentano e non diminuiscono i criteri di filtraggio. -s
- Riporta i dati visualizzati in ordine decrescente in modo da riportare prima le utenze più grandi della memoria (in base alla colonna
total
).Facoltativamente specificare node, così facendo la tabella verrà ordinata in base ai valori della colonna node. Con questa opzione il valore di node deve seguire immediatamente l'opzione-s
come mostrato qui di seguito:numastat -s2
Non includere alcuno spazio tra questa opzione ed il proprio valore. -v
- Mostra informazioni più verbose. Le informazioni per processi multipli mostreranno informazioni dettagliate per ogni processo.
-V
- Mostra le informazioni sulla versione di numastat.
-z
- Omette dalle informazioni visualizzate le colonne e le righe della tabella con un valore zero. Da notare che valori vicini allo zero approssimati a zero per facilitare la visualizzazione, non saranno omessi dall'output.
4.1.4. NUMA Affinity Management Daemon (numad)
numad è un demone di gestione dell'affinità NUMA automatico. Esso controlla la tipologia NUMA e l'uso delle risorse all'interno del sistema, in modo da migliorare dinamicamente la gestione e l'assegnazione delle risorse NUMA (e quindi delle prestazioni del sistema).
In base al carico di lavoro del sistema numad può fornire miglioramenti delle prestazioni fino ad un massimo del 50%. Per raggiungere questi livelli numad accede periodicamente alle informazioni disponibili sul file system
/proc
, per controllare la disponibilità delle risorse in base al nodo. Successivamente il demone cercherà di posizionare un numero consistente di processi sui nodi NUMA con una memoria sufficientemente allineata e in possesso di risorse della CPU, in modo da avere una prestazione ottimale. Attualmente i limiti per la gestione dei processi sono di un minimo del 50% di una CPU e di almeno 300 MB di memoria. numad cerca di mantenere un livello di utilizzo delle risorse, bilanciando le assegnazioni spostando i processi tra i nodi NUMA.
numad fornisce anche un servizio di pre-assegnazione consultabile dai vari sistemi di gestione dei compiti, che fornisce assistenza con l'associazione iniziale delle risorse della memoria e della CPU ai rispettivi processi. Questo servizio è disponibile anche se numad non è in esecuzione come demone sul sistema. Consultare la pagina man per maggiori informazioni su come usare l'opzione
-w
per una assistenza pre-assegnazione: man numad
.
4.1.4.1. Benefici di numad
numad apporta miglioramenti principalmente su sistemi con processi in esecuzione per periodi estesi che utilizzano una quantità molto elevata di risorse, ed in particolare quando i suddetti processi sono contenuti in un sottoinsieme di risorse totali del sistema.
numad puo essere anche idoneo per applicazioni che utilizzano le risorse di nodi multipli NUMA. Tuttavia i benefici forniti da numad diminuiscono all'aumentare del numero di risorse consumate in un sistema.
La possibilità che numad migliori le prestazioni quando i processi vengono eseguiti solo per pochi minuti, o in presenza di un basso consumo di risorse, è molto bassa. Altresì, sistemi con pattern di accesso alla memoria non prevedibili potrebbero non trarre alcun beneficio dall'uso di numad.
4.1.4.2. Modalità di operazione
Nota
Le statistiche sul conteggio della memoria del kernel potrebbero confondere numad dopo numerose operazioni di merge di gran parte della memoria da parte del demone KSM. Il demone KSM sarà in grado di riconoscere NUMA nelle release future. Tuttavia attualmente se il sistema presenta una quantità molto grande di memoria, sarà possibile migliorare le prestazioni disabilitando il demone KSM.
numad può essere utilizzato in due modi:
- come un servizio
- come un eseguibile
4.1.4.2.1. Usare numad come servizio
Durante l'esecuzione di numad esso cercherà di eseguire una regolazione dinamica del sistema in base al carico di lavoro del sistema.
Per avviare il servizio eseguire:
# service numad start
Per rendere il servizio persistente dopo riavvii multipli eseguire:
# chkconfig numad on
4.1.4.2.2. Usare numad come eseguibile
Per usare numad come un eseguibile eseguire::
# numad
numad continuerà la sua esecuzione fino a quando non verrà arrestato. Durante l'esecuzione le sue attività verranno registrate su
/var/log/numad.log
.
Per limitare la gestione di numad ad un processo specifico avviatelo usando le seguenti opzioni.
# numad -S 0 -p pid
-p pid
- Aggiunge il pid specifico ad un elenco di inclusione esplicito. Il processo specificato non verrà gestito fino a quando non soddisfa il limite significativo del processo numad.
-S mode
- Il parametro
-S
specifica il tipo di scansione. Impostando0
, la gestione di numad verrà limitata a processi esplicitamente inclusi.
Per arrestare numad eseguite:
# numad -i 0
L'arresto di numad non rimuoverà le modifiche eseguite per migliorare l'affinità di NUMA. Se l'utilizzo del sistema varia significativamente, una nuova esecuzione di numad modificherà l'affinità migliorando così le prestazioni.
Per maggiori informazioni sulla disponibilità delle opzioni di numad consultare la pagina man numad:
man numad
.