Cercherò di riassumere le mie esperienze ottenute nel corso dello sviluppo di ViennaCL, dove abbiamo CUDA e OpenCL backend con traduzioni principalmente 1: 1 di molti kernel di calcolo. Dalla tua domanda presumo anche che qui prendiamo principalmente le GPU.
Portabilità delle prestazioni.Prima di tutto, non esistono kernel portatili per le prestazioni, nel senso che si scrive un kernel una volta e funzionerà in modo efficiente su ogni hardware. Non in OpenCL, dove è più evidente a causa della più ampia gamma di hardware supportata, ma anche non in CUDA. In CUDA è meno evidente a causa della gamma più piccola di hardware supportato, ma anche qui dobbiamo già distinguere almeno tre architetture hardware (pre-Fermi, Fermi, Kepler). Queste fluttuazioni delle prestazioni possono facilmente comportare una variazione delle prestazioni del 20 percento a seconda di come orchestra i thread e quali dimensioni del gruppo di lavoro si scelgono, anche se il kernel è semplice come una copia buffer. Vale probabilmente anche la pena ricordare che sulle GPU pre-Fermi e Fermi era possibile scrivere kernel di moltiplicazione matrice-matrice veloci direttamente in CUDA, mentre per le ultime GPU Kepler sembra che si debba passare al linguaggio pseudo-assemblaggio PTX per avvicinarsi alle prestazioni di CUBLAS. Pertanto, anche un linguaggio controllato dal fornitore come CUDA sembra avere problemi per tenere il passo con gli sviluppi dell'hardware. Inoltre, tutto il codice CUDA viene compilato staticamente quando si esegue nvcc, che in qualche modo richiede un atto di bilanciamento tramite il flag -arch, mentre i kernel OpenCL vengono compilati in fase di esecuzione dal compilatore just-in-time, quindi in linea di principio è possibile personalizzare i kernel fino alle specifiche di un particolare dispositivo di calcolo. Quest'ultimo, tuttavia, è abbastanza coinvolto e di solito diventa un'opzione molto interessante man mano che il codice matura e mentre l'esperienza si accumula. Il prezzo da pagare è il tempo O (1) richiesto per la compilazione just-in-time, che può essere un problema in determinate situazioni. OpenCL 2.
Debug e profilazione. Gli strumenti di debug e profiling di CUDA sono i migliori disponibili per GPGPU. Anche gli strumenti di AMD non sono male, ma non includono gemme come cuda-gdb o cuda-memcheck. Inoltre, ancora oggi NVIDIA fornisce i driver e gli SDK più robusti per GPGPU, i blocchi del sistema dovuti a kernel buggy sono davvero l'eccezione, non la regola, sia con OpenCL che con CUDA. Per motivi che probabilmente non ho bisogno di spiegare qui, NVIDIA non offre più debug e profiling per OpenCL con CUDA 5.0 e versioni successive.
Accessibilità e convenienza. È molto più semplice mettere in funzione i primi codici CUDA, soprattutto perché il codice CUDA si integra piuttosto bene con il codice host. (Discuterò il prezzo da pagare in seguito.) Esistono molti tutorial sul Web, guide di ottimizzazione e alcune librerie. Con OpenCL devi leggere un po 'di codice di inizializzazione e scrivere i tuoi kernel in stringhe, quindi trovi errori di compilazione solo durante l'esecuzione quando dai i sorgenti al compilatore jit. Pertanto, ci vuole più tempo per passare attraverso un ciclo di codice / compilazione / debug con OpenCL, quindi la produttività è generalmente inferiore durante questa fase di sviluppo iniziale.
Aspetti della libreria software. Mentre i precedenti articoli erano a favore di CUDA, l'integrazione con altri software è un grande vantaggio per OpenCL. Puoi usare OpenCL semplicemente collegandoti alla libreria OpenCL condivisa e il gioco è fatto, mentre con CUDA ti viene richiesto di avere l'intera toolchain CUDA disponibile. Ancora peggio, è necessario utilizzare i compilatori host corretti per far funzionare nvcc. Se hai mai provato ad usare ad esempio CUDA 4.2 con GCC 4.6 o più recente, avrai difficoltà a far funzionare le cose. In genere, se si utilizza un compilatore più recente dell'SDK CUDA, è probabile che si verifichino problemi. L'integrazione nei sistemi di compilazione come CMake è un'altra fonte di mal di testa (puoi anche trovare ampie prove ad esempio su PETScmailing list). Questo potrebbe non essere un problema sulla tua macchina in cui hai il pieno controllo, ma non appena distribuisci il tuo codice ti imbatterai in situazioni in cui gli utenti sono in qualche modo limitati nel loro stack di software. In altre parole, con CUDA non sei più libero di scegliere il tuo compilatore host preferito, ma NVIDIA determina quali compilatori ti è permesso usare.
Altri aspetti CUDA è un po 'più vicino all'hardware (ad es. Orditi), ma la mia esperienza con l'algebra lineare è che raramente ne trai un vantaggio significativo. Esistono alcune altre librerie software disponibili per CUDA, ma sempre più librerie utilizzano più back-end di calcolo. Nel frattempo ViennaCL , VexCL o Paralution supportano tutti i backend OpenCL e CUDA, una tendenza simile può essere vista con le biblioteche di altre aree.
GPGPU non è un proiettile d'argento. GPGPU ha dimostrato di fornire buone prestazioni per operazioni strutturate e attività con calcoli limitati. Tuttavia, per gli algoritmi con una parte non trascurabile dell'elaborazione sequenziale, GPGPU non può magicamente superare la Legge di Amdahl . In tali situazioni è meglio utilizzare una buona implementazione della CPU del miglior algoritmo disponibile piuttosto che provare a lanciare un algoritmo parallelo, ma meno adatto al tuo problema. Inoltre, PCI-Express è un serio collo di bottiglia, quindi è necessario verificare in anticipo se i risparmi dalle GPU possono compensare il sovraccarico di spostamento dei dati avanti e indietro.
La mia raccomandazione Si prega di considerare CUDA e OpenCL piuttosto che CUDA oOpenCL. Non è necessario limitarsi inutilmente a una piattaforma, ma invece prendere il meglio da entrambi i mondi. Ciò che funziona bene per me è impostare un'implementazione iniziale in CUDA, eseguirne il debug, profilarlo e quindi portarlo su OpenCL con semplici sostituzioni di stringhe (è anche possibile parametrizzare le routine di generazione delle stringhe del kernel OpenCL in modo da avere una certa flessibilità nell'ottimizzazione dell'hardware di destinazione.) Questo sforzo di port consuma di solito meno del 10 percento del tempo, ma offre anche la possibilità di funzionare su altro hardware. Potresti essere sorpreso di quanto bene l'hardware non NVIDIA possa funzionare in determinate situazioni. Soprattutto, considerare il riutilizzo delle funzionalità nelle biblioteche nella massima misura possibile. Mentre un veloce e la sporca reimplementazione di alcune funzionalità spesso funziona in modo accettabile per l'esecuzione a thread singolo su una CPU, spesso ti darà scarse prestazioni su hardware estremamente parallelo. Idealmente, puoi persino scaricare tutto nelle librerie e non devi mai preoccuparti se usano CUDA, OpenCL o entrambi internamente. Personalmente non oserei mai scrivere codice bloccato dal fornitore per qualcosa su cui voglio fare affidamento tra qualche anno, ma questo aspetto ideologico dovrebbe entrare in una discussione separata.