Cos'è CUDA? Programmazione parallela per GPU

CUDA è una piattaforma di calcolo parallelo e un modello di programmazione sviluppato da Nvidia per l'elaborazione generale sulle proprie GPU (unità di elaborazione grafica). CUDA consente agli sviluppatori di accelerare le applicazioni ad alta intensità di calcolo sfruttando la potenza delle GPU per la parte parallelizzabile del calcolo.

Sebbene siano state proposte altre API per GPU, come OpenCL, e ci siano GPU competitive di altre società, come AMD, la combinazione di GPU CUDA e Nvidia domina diverse aree di applicazione, incluso il deep learning, ed è una base per alcune di i computer più veloci del mondo.

Le schede grafiche sono probabilmente vecchie quanto il PC, ovvero se si considera l'IBM Monochrome Display Adapter del 1981 una scheda grafica. Nel 1988, era possibile ottenere una scheda Wonder VGA 2D a 16 bit da ATI (la società alla fine acquisita da AMD). Entro il 1996, potresti acquistare un acceleratore grafico 3D da 3dfx Interactive in modo da poter eseguire lo sparatutto in prima persona Quake a tutta velocità.

Sempre nel 1996, Nvidia ha iniziato a provare a competere nel mercato degli acceleratori 3D con prodotti deboli, ma ha imparato man mano e nel 1999 ha introdotto la fortunata GeForce 256, la prima scheda grafica ad essere chiamata GPU. A quel tempo, il motivo principale per avere una GPU era per i giochi. È stato solo più tardi che le persone hanno utilizzato le GPU per la matematica, la scienza e l'ingegneria.

L'origine di CUDA

Nel 2003, un team di ricercatori guidato da Ian Buck ha presentato Brook, il primo modello di programmazione ampiamente adottato per estendere C con costrutti paralleli ai dati. Buck in seguito è entrato a far parte di Nvidia e ha guidato il lancio di CUDA nel 2006, la prima soluzione commerciale per l'elaborazione generica su GPU.

OpenCL contro CUDA

Il concorrente CUDA OpenCL è stato lanciato da Apple e dal gruppo Khronos nel 2009, nel tentativo di fornire uno standard per l'elaborazione eterogenea che non fosse limitato alle CPU Intel / AMD con GPU Nvidia. Sebbene OpenCL sembri attraente per la sua generalità, non ha funzionato bene come CUDA su GPU Nvidia e molti framework di deep learning non lo supportano o lo supportano solo come ripensamento una volta rilasciato il supporto CUDA.

Miglioramento delle prestazioni di CUDA

CUDA ha migliorato e ampliato il suo campo di applicazione nel corso degli anni, più o meno di pari passo con le GPU Nvidia migliorate. A partire dalla versione 9.2 di CUDA, utilizzando più GPU del server P100, è possibile ottenere miglioramenti delle prestazioni fino a 50 volte rispetto alle CPU. Il V100 (non mostrato in questa figura) è 3 volte più veloce per alcuni carichi. La precedente generazione di GPU per server, la K80, offriva miglioramenti delle prestazioni da 5 a 12 volte rispetto alle CPU.

Nvidia

L'aumento di velocità delle GPU è arrivato appena in tempo per l'elaborazione ad alte prestazioni. L'aumento delle prestazioni a thread singolo delle CPU nel tempo, che secondo la legge di Moore sarebbe raddoppiato ogni 18 mesi, è rallentato fino al 10% all'anno quando i produttori di chip hanno riscontrato limiti fisici, inclusi i limiti di dimensione sulla risoluzione della maschera del chip e sulla resa del chip durante il processo di produzione e limiti di calore sulle frequenze di clock in fase di esecuzione.

Nvidia

Domini dell'applicazione CUDA

Nvidia

Le GPU CUDA e Nvidia sono state adottate in molte aree che richiedono elevate prestazioni di calcolo in virgola mobile, come riassunto nell'immagine sopra. Un elenco più completo include:

  1. Finanza computazionale
  2. Modellazione climatica, meteorologica e oceanica
  3. Scienza dei dati e analisi
  4. Apprendimento profondo e apprendimento automatico
  5. Difesa e intelligence
  6. Produzione / AEC (Architecture, Engineering, and Construction): CAD e CAE (inclusi fluidodinamica computazionale, meccanica strutturale computazionale, progettazione e visualizzazione e automazione della progettazione elettronica)
  7. Media e intrattenimento (inclusi animazione, modellazione e rendering; correzione del colore e gestione della grana; composizione; finitura ed effetti; editing; codifica e distribuzione digitale; grafica in onda; strumenti sul set, revisione e stereo; e grafica meteorologica)
  8. Imaging medico
  9. Olio e gas
  10. Ricerca: istruzione superiore e supercalcolo (inclusi chimica e biologia computazionale, analisi numerica, fisica e visualizzazione scientifica)
  11. Sicurezza e protezione
  12. Strumenti e gestione

CUDA nel deep learning

Il deep learning ha una necessità enorme di velocità di elaborazione. Ad esempio, per addestrare i modelli per Google Translate nel 2016, i team di Google Brain e Google Translate hanno eseguito centinaia di esecuzioni TensorFlow di una settimana utilizzando GPU; avevano acquistato 2.000 GPU di livello server da Nvidia per lo scopo. Senza GPU, queste sessioni di formazione avrebbero impiegato mesi anziché una settimana per convergere. Per la distribuzione in produzione di questi modelli di traduzione TensorFlow, Google ha utilizzato un nuovo chip di elaborazione personalizzato, il TPU (unità di elaborazione del tensore).

Oltre a TensorFlow, molti altri framework DL si affidano a CUDA per il supporto della GPU, inclusi Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano e Torch. Nella maggior parte dei casi usano la libreria cuDNN per i calcoli della rete neurale profonda. Quella libreria è così importante per l'addestramento dei framework di apprendimento profondo che tutti i framework che utilizzano una data versione di cuDNN hanno essenzialmente gli stessi numeri di prestazioni per casi d'uso equivalenti. Quando CUDA e cuDNN migliorano da versione a versione, tutti i framework di deep learning che si aggiornano alla nuova versione vedono i miglioramenti delle prestazioni. Dove le prestazioni tendono a differire da framework a framework è nel modo in cui scalano su più GPU e più nodi.

Programmazione CUDA

Nvidia

Toolkit CUDA

Il CUDA Toolkit include librerie, strumenti di debug e ottimizzazione, un compilatore, documentazione e una libreria runtime per distribuire le tue applicazioni. Ha componenti che supportano il deep learning, l'algebra lineare, l'elaborazione del segnale e gli algoritmi paralleli. In generale, le librerie CUDA supportano tutte le famiglie di GPU Nvidia, ma offrono prestazioni migliori sull'ultima generazione, come la V100, che può essere 3 volte più veloce della P100 per i carichi di lavoro di formazione del deep learning. Utilizzare una o più librerie è il modo più semplice per sfruttare le GPU, a condizione che gli algoritmi necessari siano stati implementati nella libreria appropriata.

Nvidia

Librerie di deep learning CUDA

Nella sfera del deep learning, ci sono tre principali librerie accelerate da GPU: cuDNN, che ho menzionato in precedenza come componente GPU per la maggior parte dei framework di deep learning open source; TensorRT, che è l'ottimizzatore e il runtime dell'inferenza di deep learning ad alte prestazioni di Nvidia; e DeepStream, una libreria di inferenza video. TensorRT ti aiuta a ottimizzare i modelli di rete neurale, calibrare per una precisione inferiore con elevata precisione e distribuire i modelli addestrati su cloud, data center, sistemi integrati o piattaforme di prodotti automobilistici.

Nvidia

Algebra lineare CUDA e librerie di matematica

L'algebra lineare è alla base dei calcoli tensoriali e quindi del deep learning. BLAS (Basic Linear Algebra Subprograms), una raccolta di algoritmi di matrice implementati in Fortran nel 1989, è stata utilizzata da allora da scienziati e ingegneri. cuBLAS è una versione accelerata dalla GPU di BLAS e il modo più performante per eseguire operazioni aritmetiche di matrici con le GPU. cuBLAS assume che le matrici siano dense; cuSPARSE gestisce matrici sparse.

Nvidia

Librerie di elaborazione del segnale CUDA

La trasformata veloce di Fourier (FFT) è uno degli algoritmi di base utilizzati per l'elaborazione del segnale; trasforma un segnale (come una forma d'onda audio) in uno spettro di frequenze. cuFFT è una FFT accelerata dalla GPU.

Codec, utilizzando standard come H.264, codificano / comprimono e decodificano / decomprimono video per la trasmissione e la visualizzazione. Nvidia Video Codec SDK accelera questo processo con le GPU.

Nvidia

Librerie di algoritmi paralleli CUDA

Le tre librerie per algoritmi paralleli hanno tutte scopi diversi. NCCL (Nvidia Collective Communications Library) consente di scalare le app su più GPU e nodi; nvGRAPH è per l'analisi di grafi paralleli; e Thrust è una libreria di modelli C ++ per CUDA basata sulla libreria di modelli standard C ++. Thrust fornisce una ricca raccolta di primitive di dati paralleli come scansione, ordinamento e riduzione.

Nvidia

CUDA vs prestazioni della CPU

In alcuni casi, è possibile utilizzare funzioni CUDA drop-in invece delle funzioni CPU equivalenti. Ad esempio, le routine di moltiplicazione della matrice GEMM di BLAS possono essere sostituite dalle versioni GPU semplicemente collegandosi alla libreria NVBLAS:

Nvidia

Nozioni di base sulla programmazione CUDA

Se non riesci a trovare le routine della libreria CUDA per accelerare i tuoi programmi, dovrai cimentarti nella programmazione CUDA di basso livello. È molto più facile ora rispetto a quando l'ho provato per la prima volta alla fine degli anni 2000. Tra le altre ragioni, c'è una sintassi più semplice e sono disponibili strumenti di sviluppo migliori. Il mio unico svantaggio è che su MacOS l'ultimo compilatore CUDA e l'ultimo compilatore C ++ (da Xcode) sono raramente sincronizzati. È necessario scaricare i vecchi strumenti della riga di comando da Apple e passare a loro utilizzando xcode-selectper ottenere il codice CUDA da compilare e collegare.

Ad esempio, considera questa semplice routine C / C ++ per aggiungere due array:

void add (int n, float * x, float * y)

{  

       for (int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}

Puoi trasformarlo in un kernel che verrà eseguito sulla GPU aggiungendo la __global__parola chiave alla dichiarazione e chiamare il kernel utilizzando la sintassi della tripla parentesi:

aggiungi << >> (N, x, y);

Devi anche cambiare le tue chiamate malloc/ newe free/ deletein cudaMallocManagede in cudaFreemodo da allocare spazio sulla GPU. Infine, è necessario attendere il completamento di un calcolo GPU prima di utilizzare i risultati sulla CPU, con cui è possibile eseguire cudaDeviceSynchronize.

La parentesi tripla sopra utilizza un blocco filo e un filo. Le attuali GPU Nvidia possono gestire molti blocchi e thread. Ad esempio, una GPU Tesla P100 basata sull'architettura GPU Pascal ha 56 Streaming Multiprocessor (SM), ciascuno in grado di supportare fino a 2048 thread attivi.

Il codice del kernel dovrà conoscere il suo indice di blocco e thread per trovare il suo offset negli array passati. Il kernel parallelizzato utilizza spesso un ciclo grid-stride , come il seguente:

__globale__

void add (int n, float * x, float * y)

{

   int index = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   for (int i = index; i <n; i + = stride)

     y [i] = x [i] + y [i];

}

Se guardi gli esempi nel CUDA Toolkit, vedrai che c'è molto di più da considerare rispetto alle basi che ho trattato sopra. Ad esempio, alcune chiamate di funzione CUDA devono essere racchiuse in checkCudaErrors()chiamate. Inoltre, in molti casi il codice più veloce utilizzerà librerie come le cuBLASallocazioni di host e memoria del dispositivo e la copia di matrici avanti e indietro.

In sintesi, puoi accelerare le tue app con le GPU a molti livelli. Puoi scrivere codice CUDA; puoi chiamare le biblioteche CUDA; e puoi utilizzare applicazioni che supportano già CUDA.