L'utilizzo della potenza di calcolo delle GPU è diventato sempre più frequente, non solo quando si ha a che fare con la grafica 3D. Per molte applicazioni di machine learning e analisi dei dati, è infatti divenuto cruciale il supporto di questi dispositivi, dotati di processori in grado di effettuare operazioni algebriche e matriciali in maniera estremamente efficiente, grazie al calcolo parallelo che sono in grado di supportare.
Molti linguaggi di programmazione permettono, in effetti, di sfruttare le potenzialità delle GPU, tramite l'uso di librerie specifiche, o in qualche caso addirittura di appositi costrutti nativi. Ciò è però meno intuitivo in JavaScript. In effetti, essendosi diffuso inizialmente come linguaggio per i browser, la necessità dell'accelerazione hardware per le applicazioni basate su JavaScript è rimasta sempre un po' in secondo piano.
Oggi, con i nuovi trend e le nuove applicazioni di questo linguaggio in contesti diversi dal semplice sviluppo di front-end, questa necessità ha portato alla realizzazione di GPU.js, una libreria che ha esattamente lo scopo di fornire le potenzialità della GPU anche agli sviluppatori JavaScript.
Nel seguito vedremo come ottenere GPU.js, e un breve esempio di utilizzo, rimandando alla documentazione ufficiale chi fosse interessato ad un maggiore approfondimento.
Come installare GPU.js
GPU.js è disponibile su GitHub, da cui possiamo quindi scaricare il codice sorgente. È però più semplice utilizzare uno dei seguenti
https://unpkg.com/gpu.js@latest/dist/gpu-browser.min.js
https://cdn.jsdelivr.net/npm/gpu.js@latest/dist/gpu-browser.min.js
Fatto ciò, siamo pronti all'uso di GPU.js.
Utilizzare GPU.js
Partendo dal presupposto che utilizzare al meglio la GPU non è semplice, e che ciò può richiedere anche anni di esperienza per arrivare a risultati significativi, l'uso di GPU.js è relativamente semplice.
Partiamo dal codice seguente, pensato per l'esecuzione all'interno di un browser:
<script src="dist/gpu-browser.min.js"></script>
<script>
const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function(a, b) {
let sum = 0;
for (let i = 0; i < 512; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([512, 512]);
const c = multiplyMatrix(a, b);
</script>
Abbiamo creato un'istanza di GPU
, usando quindi il metodo createKernel
per definire un kernel, cioè una funzione che verrà eseguita sfruttando l'esecuzione parallela dalla GPU. Si può notare che, all'interno del codice, è utilizzata la proprietà thread
, rappresentante una delle esecuzioni parallele eseguite dalla nostra scheda grafica. È bene sottolineare, infatti, che l'uso di una libreria come GPU.js ha senso solo quando il numero di operazioni da parallelizzare è molto elevato. D'altronde, le singole unità di processing all'interno della GPU non sono migliori dei singoli core della nostra CPU: ciò che rende l'intero processo sensato è il maggior numero di unità che possono lavorare sui nostri dati.
Conclusioni
L'uso di GPU.js permette di raggiungere performance decisamente superiori rispetto a codice basato unicamente sull'uso della CPU, soprattutto all'aumentare della quantità di dati da processare. A dimostrazione di ciò, si osservi il grafico seguente:
Va detto, però, che l'uso di questa libreria richiede una preparazione non banale. A tale scopo, rimandiamo alla documentazione ufficiale del progetto, in cui è possibile partire dai concetti chiave del calcolo basato su GPU, fino ad arrivare ai moltissimi esempi già pronti che mostrano, in pratica, come sfruttare GPU.js.