# GPGPU

GPGPU (acronimo di general-purpose computing on graphics processing units, lett. "calcolo a scopo generale su unità di elaborazione grafica") indica nell'informatica l'uso di un'unità di elaborazione grafica (GPU) per scopi diversi dal tradizionale utilizzo nella grafica computerizzata.

## Caratteristiche

Il GPGPU viene impiegato per elaborazioni estremamente esigenti in termini di potenza di elaborazione, e per le quali le tradizionali architetture di CPU non hanno una capacità di elaborazione sufficiente. Per loro natura tali elaborazioni sono di tipo altamente parallelo e in grado quindi di beneficiare ampiamente dell'architettura tipica delle GPU. A tale caratteristica intrinseca a partire dal 2007 si è aggiunta l'estrema programmabilità offerta da varie soluzioni commerciali, che al succedersi delle generazioni ha aumentato non solo la propria potenza elaborativa ma anche la propria versatilità. Tale evoluzione delle architetture video si è gradualmente attuata anche perché la stessa grafica 3D dei videogiochi si è enormemente trasformata nel tempo; un tempo essi erano basati su un insieme di istruzioni fisse e predefinite, ma progressivamente si è sviluppato un approccio nel quale le GPU vengono completamente programmate utilizzando gli shader, caratteristica che ha aperto di conseguenza anche nuovi scenari di utilizzo a questo tipo di soluzioni hardware. Tale programmabilità ha preso appunto il nome di Shader model.

## Scenari tipici di elaborazione GPGPU

Le applicazioni che sono in grado di avvantaggiarsi significativamente della potenza di calcolo delle moderne GPU sono solo una ristretta parte dell'intero panorama software, in quanto per sfruttare le caratteristiche di tali architetture è necessaria un'elevata parallelizzazione del codice, una caratteristica tipica di alcuni problemi scientifici ma non tutti; tra questi si possono citare innanzitutto l'elaborazione di immagini in genere, come per esempio quelle mediche, o di ricerca geologica tra cui la ricerca di giacimenti petroliferi e di fonti naturali, oltre che l'analisi di modelli di rischio finanziari.
Altre categorie di applicazioni sono invece caratterizzate dalla necessità di un'elevata logica di controllo del processo di calcolo e tale funzione è svolta egregiamente dalle tradizionali CPU ma in maniera altamente inefficiente dalle architetture delle GPU. Tra queste tipologie di applicazioni si possono ricordare i database, la compressione dei dati e i generici algoritmi ricorsivi.
Alcuni settori scientifici che beneficiano del GPGPU sono:
* Fisica: Equazioni di Eulero, Equazioni di Navier-Stokes, meccanica quantistica, Metodi reticolari di Boltzmann.
* Chimica e biologia: Simulazioni Monte-Carlo, bioinformatica, modellazione proteica.
* Matematica: Trasformate di Fourier, crittografia.
* Astronomia e astrofisica: radioastronomia, decodifica segnali spaziali, compensazione immagini.
* Medicina: Immagini mediche, supporto alle decisioni diagnostiche.
* Sicurezza informatica: crittografia, MD6.
* Criptovalute: utilizzo delle GPU per il mining.
* Calcolo distribuito: accelerazione delle applicazioni BOINC attraverso le GPU consumer.
Diversi programmi fanno uso del GPGPU, tra cui: Adobe Photoshop, Autodesk Maya, GIMP, Autodesk AutoCAD, Blender, SolidWorks, MATLAB, CHARMM (dinamica molecolare), AMBER (chimica computazionale), FFmpeg, X264, LibreOffice, OpenMM (simulazioni molecolari).

## Principali benefici dell'elaborazione GPGPU

I benefici dell'utilizzo di una GPU per svolgere elaborazioni di tipo diverso dall'ambito grafico sono molteplici e tra questi si possono ricordare i seguenti:

### Vantaggi prestazionali

La caratteristica più eclatante di questo tipo di utilizzo delle GPU è, come detto, l'enorme potenza teorica offerta da tali soluzioni, e di conseguenza il ridotto tempo di elaborazione, quando confrontato con analoghe elaborazioni svolte dalle CPU. Va detto comunque che il passaggio dell'elaborazione del codice verso la GPU richiede l'ottimizzazione delle applicazioni stesse al fine di integrare il supporto alle caratteristiche peculiari di tali architetture; si tratta spesso di una riscrittura totale di intere parti di codice e ovviamente gli sviluppatori devono tenere conto di tali fattori in fase di sviluppo per ovvie politiche commerciali, ma dal punto di vista puramente prestazionale si possono ottenere incrementi anche di 100 volte rispetto a quanto offerto dalle tradizionali CPU. Non si tratta quindi di incrementi del 20 o 30%, e nemmeno di un raddoppio della potenza, ma addirittura di una "centuplicazione" della potenza elaborativa, e di conseguenza i tempi di calcolo si riducono di 100 volte.

### Costo d'acquisto

Il costo di una qualunque GPU è allineato a quello di una CPU appartenente alla stessa fascia di mercato, quindi una GPU di fascia alta può venire a costare circa 600 euro, al pari di una CPU di pari fascia. Considerando che, allo stesso prezzo, una GPU è in grado di offrire prestazioni teoriche di gran lunga superiori, appare chiaro come ottimizzare i software per il corretto sfruttamento di queste architetture consenta di contenere efficacemente i costi migliorando notevolmente le cosiddette "prestazioni per watt" e di conseguenza l'efficienza dell'elaborazione.

### Tasso di aggiornamento tecnologico

Il susseguirsi delle generazioni delle architetture di GPU è decisamente più veloce rispetto alle evoluzioni disponibili nel campo delle CPU. Le architetture delle CPU, spesso durano quasi immutate per anni (l'architettura NetBurst di Intel è durata ben 6 anni) e solo dal 2005 la tendenza sta diventando quella di presentare nuove architetture ogni due anni (cfr. Intel Tick-Tock), mentre le architetture relative alle GPU in genere durano dai 12 ai 18 mesi massimo (in passato si sono avuti aggiornamenti di tali architetture anche in soli 6-8 mesi). Inoltre, mentre le nuove architetture di processore in genere aumentano le prestazioni, a parità di clock, del 20-30% massimo, per quanto riguarda le GPU, da anni si assiste al raddoppio puro della potenza elaborativa ad ogni nuova generazione.

### Consumo/prestazioni

Sebbene i produttori di CPU si siano impegnati molto sul fronte dell'efficienza energetica e del contenimento dei consumi massimi, i produttori di GPU sembrano aver finora ignorato tale aspetto nella progettazione delle nuove soluzioni. Tuttavia, l'enorme potenza elaborativa teorica delle GPU compensa grandemente l'elevato livello di consumo energetico e di conseguenza il rapporto consumo/prestazioni delle diverse soluzioni è nettamente a vantaggio delle GPU rispetto alle CPU.

## Generazione di un'immagine tridimensionale, attraverso una GPU

Il processo di creazione di un'immagine tridimensionale consta dei seguenti punti:
* definizione dei punti (o triangoli) da disegnare
* trasformazione delle coordinate dei punti
* interpolazione dei punti per creare una figura
* colorazione dei pixel della figura che risultano visibili
Grazie agli shaders è possibile istruire la GPU (Graphics Processing Unit) su come comportarsi nella fase di trasformazione dei punti (Vertex shader) e nella fase di colorazione dei pixel (Pixel shader).

## Principi di un'elaborazione GPGPU

Per poter implementare un motore GPGPU bisogna astrarre una macchina di Turing equivalente dall'architettura della GPU.
Innanzitutto bisogna fare in modo che gli Shaders possano leggere dei dati in input. Per risolvere questo problema si può pensare di scrivere i dati in input in alcune texture e farle campionare dagli shaders.
Ovviamente bisognerà creare delle buone funzioni di indirizzamento in grado di tradurre le coordinate di indirizzamento (solitamente degli interi) nelle coordinate di campionamento delle texture (due valori decimali compresi tra 0 e 1).
Bisognerà poi scrivere un programma che giri sulla scheda grafica in grado di elaborare i dati letti e produrre i risultati desiderati.
Per questa fase si hanno diverse scelte di codifica:
* Scrivere del codice in un linguaggio assembler supportato dalle librerie grafiche utilizzate
* Scrivere il programma in un linguaggio di alto livello (HLSL, GLSL)
Infine bisognerà eseguire il "rendering" dei dati per produrre i risultati desiderati con l'accortezza di salvare tale output su una texture reperibile in seguito.
Per realizzare un motore GPGPU attualmente bisogna utilizzare delle librerie grafiche che supportino lo shader model (DirectX, OpenGL). Sono comunque attivi diversi progetti per permettere al programmatore di usare il GPGPU senza dover conoscere tali librerie. I progetti più attivi possono essere trovati su siti come www.gpgpu.org o hgpu

## Supporto Hardware

I principali produttori di schede video, AMD, nVidia ed Intel, stanno investendo per migliorare la resa delle loro architetture nei calcoli General Purpose:
* ATI/AMD aveva introdotto le prime schede video consumer in grado di supportare il calcolo general purpose nel 2008 con le schede video della famiglia HD4xxx, seppur appoggiandosi ancora alla tecnologia CTM. La serie di GPU dedicate al calcolo è quella della famiglia Instinct.
* nVidia invece, con le schede GeForce serie 8 ha introdotto la possibilità di svolgere calcolo GPGPU anche su schede consumer. A giugno 2007 inoltre ha presentato la tecnologia Tesla che indica un'intera famiglia di soluzioni hardware finalizzate espressamente all'elaborazione GPGPU.
* Intel ha introdotto, nel 2013, schede espressamente dedicate al GPGPU (Xeon Phi).
Le schede dedicate (Instinct, Tesla e Phi) non sono a tutti gli effetti schede video, in quanto spesso sono sprovviste di uscite video per potervi collegare un monitor, ma sono equiparabili a dei coprocessori matematici molto potenti, basati sulle architetture GPU dedicate; queste schede sono utilizzate all'interno di sistemi HPC espressamente dedicati, in modalità di calcolo ibrida CPU/GPU.

## Principali linguaggi di programmazione GPGPU

* CUDA è la tecnologia proprietaria di Nvidia per il calcolo su GPU.
* ROCm e HIP sono tecnologie similari a CUDA, ma sono open source e sono sviluppate da AMD
* OpenMP Target è la tecnologia di OpenMP deputata al calcolo su acceleratori
* OneAPI è il nuovo standard promosso da Intel basato sullo standard SyCL di Khronos che punta ad diventare linguaggio universale come tentò OpenCL senza successo in passato.
* OpenCL (Open Computing Language) è una libreria basata sul linguaggio ANSI C e C++14.
* C++ AMP è una libreria open, derivata da Microsoft dalle sue DirectX 11.
* OpenACC è una libreria open source sviluppata inizialmente da Nvidia, Cray, Caps e PGI.
* CTM (Close to Metal) è una vecchia tecnologia abbandonata di AMD. Ha permesso di utilizzare le GPU, a partire dalla serie Radeon R5xx, come processori vettoriali a virgola mobile a 32bit, con prestazioni superiori alle librerie grafiche (DirectX e OpenGL). Tale caratteristica lo rendeva uno strumento di calcolo molto potente per certe operazioni tra cui, nelle intenzioni di ATI, la gestione dei motori fisici dei videogiochi.
* DirectCompute è una libreria Microsoft derivata, come C++AMP, dalle librerie DirectX.

### Differenze tra l'approccio ATI/AMD e quello nVidia

L'approccio di nVidia con CUDA è certamente più semplice da acquisire da parte dei programmatori rispetto al CTM di ATI. Malgrado quest'ultimo consenta l'interazione con la GPU ad un livello più potente rispetto a quanto offerto da CUDA, rimane però anche più difficile da implementare dato che viene richiesta la conoscenza di un linguaggio di tipo assembly, in luogo del tradizionale C++ previsto dalla soluzione di casa nVidia. CTM inoltre, proprio perché basato su un linguaggio di programmazione di più basso livello, è specifico per una precisa famiglia di GPU, mentre CUDA ha dalla sua la flessibilità di poter spostare applicazioni sviluppate in qualsiasi momento, anche su future generazioni di GPU nVidia.
Con il passaggio di ATI/AMD alle soluzioni OpenCl, il problema del legame di CTM con l'hardware è stato superato, offrendo il linguaggio Opencl (basato su C++) un accesso di alto livello ai più diversi dispositivi hw, molto più di quelli accessibili dalle librerie CUDA.