Località NUMA dell'IA locale: perché il posizionamento della memoria modifica la velocità di alimentazione dell'acceleratore

Eva Wong è la Technical Writer e smanettatrice residente di ZimaSpace. Una geek da sempre con una passione per homelab e software open-source, si specializza nel tradurre concetti tecnici complessi in guide accessibili e pratiche. Eva crede che l'auto-ospitare debba essere divertente, non intimidatorio. Attraverso i suoi tutorial, dà potere alla comunità di demistificare le configurazioni hardware, dalla costruzione del loro primo NAS al dominio dei container Docker.

La località NUMA modifica la velocità di alimentazione dell’acceleratore, perché la preelaborazione e i trasferimenti sul sistema host sono più rapidi quando i thread della CPU, le pagine di memoria e il dispositivo condividono un percorso vicino.

In una workstation domestica multi-socket, ogni core della CPU può indirizzare tutta la RAM, ma il costo di accesso non è uniforme. Una GPU o un altro acceleratore è solitamente collegato tramite il root complex PCIe di un socket. Se la preelaborazione viene eseguita su un altro nodo e i buffer vengono allocati lì, i dati possono attraversare l’interconnessione tra socket prima di raggiungere il dispositivo, aumentando la contesa e la latenza variabile.

NUMA rende osservabile la distanza dalla memoria dell’host

Un sistema NUMA divide CPU e memoria in nodi con distanze di accesso differenti. Linux alloca comunemente una pagina sul nodo locale alla CPU che la genera per la prima volta. Il posizionamento dei thread durante il caricamento del modello o la preparazione degli input può quindi determinare dove risiedono fisicamente i buffer di grandi dimensioni.

La documentazione di Linux sulle policy di memoria NUMA descrive le policy per attività, VMA, memoria condivisa, binding, preferenza e interleaving. Nota inoltre che le policy influiscono principalmente sulle pagine allocate dopo la loro installazione, rendendo importante l’ordine di inizializzazione. Questa distinzione rimane importante in condizioni operative domestiche realistiche.

Per l’inferenza locale, il percorso critico può includere tokenizzazione, decodifica delle immagini, preparazione dei tensori, buffer bloccati e trasferimenti verso il dispositivo. Un posizionamento remoto aggiunge un collo di bottiglia sul sistema host anche quando l’acceleratore stesso segnala capacità di calcolo inutilizzata. Lo stato intermedio dovrebbe rimanere visibile durante la diagnosi e la revisione successive.

La topologia PCIe collega un acceleratore a specifici nodi CPU

Il percorso più breve tra host e dispositivo passa normalmente dal socket della CPU il cui root complex gestisce l’acceleratore. Vincolare i thread CPU del worker e la policy di allocazione a quell’area può migliorare la larghezza di banda e ridurre la variabilità, soprattutto quando input di grandi dimensioni o trasferimenti frequenti mantengono occupato il collegamento.

Le indicazioni NUMA di NVIDIA per CUDA includono raccomandazioni NUMA e avvertono che il bilanciamento automatico può peggiorare le applicazioni GPU in alcuni casi. Raccomandano di esaminare la topologia e regolare la policy per il nodo effettivo, invece di basarsi sui numeri dei nodi.

Il posizionamento è un problema di grafo, non una regola secondo cui il nodo zero è il più veloce. L’associazione corretta dipende dal cablaggio della scheda madre, dalla configurazione IOMMU, dagli altri dispositivi e dal fatto che più worker competano per gli stessi canali di memoria o collegamenti PCIe.

Il binding può danneggiare le prestazioni quando il carico usa più di un nodo

Vincolare rigidamente la memoria a un solo nodo può esaurirne la larghezza di banda o la capacità mentre gli altri nodi restano inattivi. Una pipeline può usare una GPU vicina a un socket, ma anche una scheda di acquisizione, un dispositivo NVMe o un secondo acceleratore vicino a un altro. Un posizionamento può ottimizzare i trasferimenti rallentando però la preelaborazione o l’archiviazione.

Il progetto GPU affinity di NVIDIA associa i processi ai core CPU collegati alle GPU e osserva che un’affinità corretta può stabilizzare le prestazioni. Le sue diverse modalità mostrano perché gli ambiti univoco, contiguo, socket e NUMA siano adatti a carichi di lavoro multiprocesso differenti.

Il confine del guasto è rappresentato da un benchmark su un singolo dispositivo generalizzato all’intero server. Non applicare il binding alla cieca su sistemi con memoria integrata, macchine a nodo singolo o pipeline che attraversano diversi dispositivi; misura latenza end-to-end, larghezza di banda e contesa con il livello di concorrenza previsto.

Esegui benchmark sulla topologia, non solo sull’acceleratore

Mappa i nodi CPU, la capacità della memoria, i dispositivi PCIe e la località dell’acceleratore. Esegui lo stesso carico di inferenza con posizionamento predefinito, binding solo della CPU, binding solo della memoria e binding abbinato di CPU e memoria. Registra la larghezza di banda host-dispositivo, il posizionamento delle pagine, i token al secondo e la latenza p95.

Se gli shard del modello provengono da uno storage di rete, come nel caso dello storage di rete dei modelli, separa il tempo di lettura dei file dal posizionamento delle pagine e dal trasferimento verso il dispositivo. Riscalda gli stessi dati per ogni esecuzione, quindi ripeti il test con i worker concorrenti previsti per evidenziare la contesa sui canali di memoria.

Adotta il binding solo se la topologia abbinata migliora in modo ripetibile i risultati end-to-end senza penalizzare un altro servizio. Se i miglioramenti scompaiono dopo il riscaldamento o si invertono durante la concorrenza, lascia flessibile il posizionamento oppure isola soltanto i thread e i buffer critici per i trasferimenti.

Hub Tecnologico e AI

Altro da leggere

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.