Il fu Maxwell-Pascal

Il nostro autore “nessuno” mi ha mandato questo articolo prima di Natale. Solo ora, per di più intorno a mezzanotte, riesco a metterci la testa. Grazie a nessuno, del post come sempre straordinariamente accurato, e della pazienza. A breve la second parte.
PIC_00

# 1.0 Indovinare il futuro

Con l’articolo precedente, scritto oltre un anno fa, oltre all’analisi storica degli avvenimenti prima del lancio di Volta, si è cercato di indovinare quello che sarebbe dovuto essere il successore dell’architettura Pascal usando le poche informazioni disponibili e facendo uso delle esperienze e delle scelte precedenti condotte da Nvidia al lancio delle nuove architetture. Alla luce dei fatti che oggi conosciamo, la previsione è risultata errata sotto diversi punti di vista, sia tecnici che di strategia adottata. Cerchiamo quindi di capire cosa è diverso e anche di valutare quale sono le implicazioni di queste inattese differenze, alcune sorprendentemente positive altre decisamente no.
L’argomentazione sarà un po’ varia e cercherà di coprire i punti salienti di questa nuova offerta di tecnologia sul mercato che ha diverse cose di cui parlare.

L’articolo è abbastanza lungo e farà riferimento ad alcune informazioni che sono state date negli articoli precedenti, principalmente quello riguardante i processi produttivi.
Inserisco qui un mini glossario di parole che troverete in questo articolo con definizione spicce:
– die: pezzo di silicio rettangolare che contiene un circuito integrato.
– latenza: tempo (o numero di cicli) che trascorre da quando si fa una richiesta a quando si ottiene la risposta.
– efficienza: valore usato per misurare l’efficacia di qualcosa. Si calcola come rapporto tra una quantità effettivamente prodotta rispetto a una qualsiasi risorsa necessaria perché il processo sia svolto. Per esempio lavoro compiuto rispetto all’energia, al tempo o allo spazio consumati. Nel nostro caso ha significato quando lo si paragona a qualcosa che fa lo stesso lavoro con necessità diverse.
– overhead: lavoro supplementare necessario per completare il compito assegnato dovuto alla complessità del sistema che svolge il compito. Maggiore l’overhead, minore l’efficienza di esecuzione.

Così scrivevo a fine 2017, quando non si conosceva ancora il nome effettivo della architettura Nvidia che avrebbe preso il posto di Pascal nel mercato consumer (candidati erano Volta, Ampere e Turing):

“Di sicuro non vi saranno le funzionalità legate al calcolo puro, quindi no HBM2, i vari bus NVLink, le unita FP64, i tensor core, le cache aggiunte, lo scheduling avanzato e probabilmente la segmentazione delle SM in 64 ALU al posto delle normali a 128 ALU (a meno che la segmentazione correttamente gestita permetta in qualche modo di ottenere prestazioni migliori con i lavori imposti dalle nuove tecniche di Async Computing). È presumibile che il GV102 sia il GV100 senza tutto questo, e quindi con le sole 5376 (se messo in commercio completo con tutti i 42 TPC abilitati) esattamente come il GP102 è rispetto al GP100.
Non si sa se le ALU integer, che in Volta possono funzionare parallelamente a quelle floating point saranno incluse anche nelle GPU minori (non trovo uno scopo utile nel gaming alla cosa, per cui non credo, ma magari Nvidia ne ha inventate una delle sue per avere qualche feature nuova rispetto alla concorrenza). Con le nuove unità FP32 che possono eseguire 2xFP16 la presenza o meno del packed math è solo questione di quale strategia vuole adottare, ovvero se crede che l’FP16 nel mondo consumer sia un vero vantaggio o meno.”

A fine 2018 Nvidia ha finalmente presentato e lanciato sul mercato la nuova architettura post Pascal. Cosa è dunque vero o falso di quanto pronosticato?
Rispetto alla mia semplicistica previsione, che prendeva come riferimento la presentazione del GP102 dopo il GP100, è più quello che non è stato che quello che è stato.
Turing ha sorpreso un po’ tutti, introducendo nel mercato consumer elementi che prima non erano presenti neanche nelle architetture professionali. Il tentativo evidente è quello di rivoluzionare il mercato sotto diversi aspetti, questa volta non con parole o vacui slogan stampati su colorate slide, ma proprio con nuove reali funzionalità avanzate (e tanto tanto silicio).

Cominciamo con quanto supposto possibile ed effettivamente avvenuto. Ogni punto importante sarà approfondito successivamente, per cui non preoccupatevi se alcune cose sono solo elencate sinteticamente:
– Dimensione del die aumentata (e non di poco)
– Il calcolo combinato 2xFP16 (packed math), considerato probabile, è presente.
– Partizionamento SM in 2×64 CUDA core invece che 1×128 CUDA core considerato possibile è presente
– Unità integer in funzione parallelamente a quelle floating point considerato possibile è presente (Nvidia ovviamente ne sa più di me sul perché questo era un punto da implementare anche nel mercato consumer)
– No unità FP64 dedicate
– Frequenze non aumentate (avevamo visto che già con il GV100 queste non erano maggiori rispetto al GP100, quindi era prevedibile che il nuovo PP non permettesse di eccedere in tal senso)
– Uso della memoria GDDR6 (ma questo era quasi ovvio, l’HBM non ha alcun senso economico oltre che pratico nel mercato consumer)
– Più in generale, con quanto conosciuto del nuovo processo produttivo (i 12nm di TSMC) usati in origine anche per il GV100, l’analisi esposta nell’articolo precedente ha correttamente pronosticato che, come con Maxwell, le maggiori prestazioni delle nuove GPU sono dovute ad un miglioramento architetturale piuttosto che ad un mero aumento delle unità di calcolo. Tale aumento prestazionale ovviamente è andato a discapito della dimensione del die del chip che riserva qualche sorpresa.

Cosa invece è diverso da quanto ipotizzato:
– La quantità di unità di calcolo è diminuita rispetto alla generazione precedente (!)
– La nuova interfaccia per lo SLI è l’NVLink (!)
– Ci sono i tensor core (!!)
– E sorpresa delle sorprese… ci sono nuove unità chiamate RT per aumentare le prestazioni degli algoritmi di ray tracing (!!!)

Sembra che l’elenco delle cose ritenute possibili ed poi risultate avverate sia più lungo di quelle sbagliate e quindi che la previsione può essere considerata buona. In verità quello che è diverso ha così tanta importanza e con grande impatto strategico per il futuro che si può affermare senza ombra di dubbio che quanto era stato azzeccato dalla previsione fatta è roba di poco conto rispetto a quanto Nvidia ha effettivamente realizzato.

Indipendentemente da come andrà nell’immediato futuro, Nvidia ha presentato una delle architetture più rivoluzionarie mai create. Dopo l’introduzione del T&L HW con la prima GeForce 256 (anno 1999) e degli shader unificati con il G80 (soluzione tecnologicamente avanzata adottata in contemporanea anche da ATI, poi AMD quindi con meno effetto mediatico, anno 2006), nel 2018 propone l’accelerazione degli algoritmi di ray tracing. Quindi non più solo risorse destinate all’aumento di prestazioni delle stesse funzionalità del passato sulla base di una pipeline nata negli anni ’90 ed evoluta con gli stressi principi fino ad oggi, ma sta invitando a cambiare completamente approccio alla generazione delle immagini 3D. Il successo di questo “invito” è ancora da vedere nei tempi di attuazione, ma sicuramente avverrà (2, 5, 10 anni?), come potrete intuire dalla descrizione su cosa è il ray tracing, per chi non lo sa già.

E’ difficile dare un ordine ai molti argomenti che nascono a pioggia da questa architettura così diversa.
L’intento come sempre rimane quello di dare una descrizione tecnica e valutare il possibile l’impatto che ciascuno di questi avrà nel futuro sull’evoluzione del mercato.
L’invito, come sempre, è quello di comprendere il perché delle cose e poi valutare il come e il quando. E come sempre, non è detto che la mia interpretazione dei fatti sia corretta, quindi cercate di sforzarvi a fare analisi per vostro conto e trovare nuovi modi (coerenti) di collegare le cose, sia per quelle presenti e poi anche per il futuro.

PIC_20

# 2.0 Ray tracing Real Time, la nuova parola d’ordine della grafica computerizzata secondo Nvidia

Cominciamo con il parlare brevemente di ray tracing, cosa è e perché.
La tecnica di ray tracing, letteralmente “del tracciamento del raggio”, in termini semplici simula con diverse tecniche più o meno efficienti un raggio di luce lungo tutto il suo percorso in una scena virtuale, dalla sorgente luminosa fino all’occhio/camera/schermo (o in maniera inversa, dallo schermo al resto della scena) per determinare alla fine quale è il colore del pixel che viene colpito da tale raggio.
Per sapere più in dettaglio come funziona il ray tracing trovate migliaia di descrizioni che non vi riporto qui, potete partire dalla solita wikipedia: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)
La tecnica del ray tracing è stata ipotizzata negli anni ’70 e da sempre è la tecnica più “agognata” per simulare la luce e creare ambienti realistici tramite la computer grafica, ovvero la grafica sintetica, quella generata completamente dal computer.

PIC_21
Immagine semplificata del principio di funzionamento della tecnica di raytracing

Ho detto agognata perché è una tecnica che usa procedure molto complesse che richiedono una grande quantità di risorse di calcolo non sempre disponibili e che nel tempo si è evoluta continuamente per migliorare la simulazione della luce man mano che la potenza computazionale è aumentata di anno in anno. Gli algoritmi sono oggi così evoluti e perfezionati nella simulazione (fisica) di molti dettagli del comportamento della luce al punto tale che siamo in grado di creare lungometraggi in computer grafica tramite questa tecnica con risultati strabilianti per quanto riguarda la qualità e la similitudine con la realtà delle immagini prodotte (foto realismo, vedesi il film Avatar, per esempio).
Il costo di questo tipo di creazione di immagini sintetiche come detto è la potenza computazionale necessaria e quindi il tempo di calcolo per ogni singolo frame, che non può essere condotta in tempo reale (ovvero, il tempo di generazione non è uguale o inferiore al tempo di vita dello stesso frame in un video con determinate caratteristiche di fluidità e quindi la generazione delle immagini deve essere prodotta in anticipo rispetto alla visualizzazione dell’animazione). Servono mesi se non anni di computazione continua per avere una sequenza di un’ora abbondante di filmato, ad alta risoluzione e massima qualità per quanto riguarda il colore necessario per la proiezione cinematografica. E’ chiaro che i costi associati per questo tipo di elaborazioni è fuori dalle capacità dei comuni utenti consumer, necessitando server appositi dai costi e soprattutto dai consumi elevatissimi.

Indipendentemente da quanta potenza computazionale è a disposizione, che determina solo i tempi di produzione, la tecnica di ray tracing è quella (a oggi) che garantisce la massima accuratezza, tramite simulazione fisica, di come realmente interagisce la luce all’interno di una scena, ed è quindi quella cui tutti aspirano di poter usare sin dagli albori dell’uso dei computer per generare grafica foto realistica.

## 2.1 Ray tracing vs rasterizzazione

Per via della sua inapplicabilità per i costi e tempi di rendering su sistemi consumer, l’industria si è mossa ad usare tecniche diverse per creare immagini che siano “fabbricabili” in tempo reale, ovvero dove i tempi di creazione sono inferiori al tempo per cui frame rimangono visibili, in modo tale che siano generati sequenzialmente poco prima di essere visualizzati senza ritardare quello successivo e quindi interrompendo la fluidità dell’animazione. Queste tecniche, denominate “di [b]rasterizzazione[/b]”, sono un surrogato della simulazione matematica della fisica della luce che invece è effettuata tramite ray tracing, e semplificano al massimo l’applicazione di vari algoritmi tramite l’uso di unità di elaborazione generica. Per operazioni particolari, non eseguibili in tempi utili tramite computazione general purpose, sono usati anche acceleratori basati su funzioni di tipo fixed, ovvero dove l’algoritmo è determinato in HW e non è adattabile, ma è eseguito molto velocemente, al fine di ottenere risultati che sono un compromesso accettabile tra qualità e velocità necessari per un videogioco, che di certo non pongono la qualità finale comparabile con un risultato foto realistico.

Le varie unità di tipo fixed function che tutti ormai conosciamo presenti in una GPU, quali le TMU, le ROPs, ma anche i motori geometrici finora adottati, sono parte di una pipeline (sequenza di passi) sviluppata per supportare la tecnica di rendering denominata di “rasterizzazione”. Erano unità di tipo fixed anche i pixel e vertex shader prima che venissero unificati in unità di computazione più generica in grado di eseguire codice più general purpose rendendoli così più flessibili (ma meno efficienti, ricordate la comparazione tra Terascale di AMD e le architetture post Tesla di Nvidia?) ad elaborare dati che non siano necessariamente da/per strutture grafiche e necessari per applicare effetti complessi.
Dalla metà degli anni ’90 a oggi tutte le aziende che hanno creato processori in grado di generare grafica 3D hanno sempre sviluppato tecniche per ottimizzare la pipeline di rasterizzazione e le stesse librerie grafiche (Direct3D, OpenGL, Glide, Vulkan) sono state pensate e sono evolute nel tempo per usare questa tecnica. Sono quindi più di 20 anni che si sfrutta la rasterizzazione, ovviamente evoluta e ottimizzata nel tempo come è visibile dagli sviluppi delle varie GPU da allora fino ad oggi: dalle poche decine di milioni di transistor a 50MHz della prima Voodoo agli oltre 17 miliardi di transistor a 2GHz di TU102 (la GPU montata nella RTX2080Ti) di oggi, lo sforzo e gli enormi investimenti in questo tipo di elaborazione sono più che evidenti.
Da menzionare che l’unico tentativo fatto per uscire dai vincoli della rasterizzazione, condotto da Intel con il suo progetto Larrabee nel 2009, è fallito perché incapace di eseguire il lavoro delle unità fixed function sviluppate ed usate da AMD e Nvidia in maniera altrettanto efficiente, sia in termini di consumi, di spazio ma anche di prestazioni.

PIC_22

Differenti pipeline per le due tecniche di rendering. Notare come la pipeline di ray tracing sia più semplice, anche se richiede più potenza computazionale

Oggi siamo ad un punto in cui voler incrementare la qualità delle immagini usando queste tecniche surrogate comporta notevoli difficoltà, sia in termini computazionali che crescono esponenzialmente, sia per quanto riguarda il lavoro necessario per sistemare tutti gli effetti collaterali (artefatti) che queste tecniche surrogate necessitano. Tutti gli interventi ai driver che Nvidia e AMD sono costretti a fare al rilascio di ogni gioco sono principalmente dovuti a questo tipo di problemi che devono essere corretti, e poco sorprendentemente sembra che gli sviluppatori abbiano deciso che è meglio che siano corretti dai driver, il cui costo di manutenzione è a carico del produttore di GPU, piuttosto che direttamente dal codice del gioco, il cui costo di fixing è a carico dello sviluppatore (o della casa di sviluppo per cui lavora).

Per fare un esempio banale, il calcolo delle ombre nei giochi è un’operazione che viene svolta in maniera “sporchissima”, con risultati di qualità variabili e non sempre consistenti, perché non c’è un metodo semplice che si può applicare con la rasterizzazione per calcolarle senza tenere conto esattamente di dove si trovano la, o meglio le sorgenti luminose e il contributo della illuminazione globale oltre che delle altre superficie della scena che indirettamente potrebbero riflettere o bloccare la luce e creare ulteriori proiezioni d’ombra. Per farlo, serve una tecnica simile a quella del ray tracing, ma che come abbiamo detto è impossibile da realizzare in tempo reale su HW di fascia consumer.

Come si è notato, il passaggio dalle DX9 alle più moderne DX12 non ha portato grandi cambiamenti di qualità nelle immagini prodotte: sono migliorati gli algoritmi, si sono ridotti i tempi di calcolo tramite nuove tecniche di elaborazione differite, si sono introdotte nuove funzionalità geometriche, si è aumentato il supporto ad una maggiore parallelizzazione sia su CPU che su GPU, ma alla fine, nonostante il numero maggiore di poligoni e qualità superiori di texture, il più del lavoro extra per migliorare la grafica è a carico degli shader che devono elaborare qualsiasi cosa che le funzioni di tipo fisso non consentono di fare. Alte risoluzioni e qualità che aumenta in maniera logaritmica rispetto alla potenza computazionale a quanto pare stanno facendo sorgere il dubbio sulla opportunità di farcire le GPU di unità di calcolo general purpose per continuare a evolvere un modello di generazione d’immagine che ha le radici nelle limitazioni HW presenti 20 anni fa e che ai tempi necessitava di essere adottato per poter generare immagini sintetiche in tempo reale.

Non ultimo è il problema della scalabilità delle architetture: il sempre maggior numero di unità di elaborazione inserite nelle GPU producono problemi di efficienza computazionale (in maniera diversa a seconda dell’architettura) e far scalare la potenza computazionale in maniera lineare con il numero di queste unità sta diventando un problema. Le DX12 sono un tentativo di aumentare le prestazioni, a parità di HW, cercando di diminuire “i tempi morti” che in un sistema complesso come una GPU inevitabilmente si creano. Il problema è che richiede un maggior lavoro da parte dei programmatori che non è detto vogliano farsi carico dei problemi di scalabilità dei produttori di GPU oltre ai già citati problemi di creare tecniche surrogate per nuovi effetti più realistici.
La questione aperta da Nvidia con Turing è se la potenza di elaborazione a disposizione oggi è o meno sufficiente a cambiare il paradigma di elaborazione verso la più generica, sofisticata, precisa e “pulita” (e quindi meno onerosa da parte degli sviluppatori, che è ciò che chiedono) tecnica di ray tracing.

# 3.0 Turing, la rivoluzione?

PIC_30
La “vecchia” architettura Pascal
PIC_31
La nuova architettura Turing

Con Turing Nvidia ha portato nel mercato consumer GPU con nuove funzionalità avanzate che le fanno affermare che il ray tracing in real time è oggi possibile.

Turing infatti ha integrato due nuove unità di calcolo usabili per ray tracing: i tensor core (già visti sul GV100) che sono usate dai filtri di output (vedesi dopo) e le nuove unità RT che accelerano le ricerche binarie il cui peso negli algoritmi di ray tracing (ma non solo) è molto impattante in termini prestazionali.

Nvidia ha presentato tre nuove GPU basate sull’architettura Turing:
– il TU102, che è la GPU più grande con i suoi 754mm2 che va a equipaggiare la nuova regina delle schede grafiche, la RTX2080Ti (prezzo di listino di 1100 dollari)
– il TU104, da 545mm2 che è montato sulla RTX2080 (prezzo di listino di 800 dollari)
– il TU106, da 445mm2 che è invece montato sulla RTX2070 (prezzo di listino di 600 dollari)
Una quarta GPU, il TU108, è stata annunciata ma non è chiaro quali e quante unità integrerà. Sembra che per questa classe di GPU le unità RT non saranno presenti perché troppo poco numerose per poterci ricavare qualche cosa di utile.

Delle tre GPU di cui abbiamo le specifiche balzano subito all’occhio, oltre al prezzo, le dimensioni dovute alla presenza delle nuove unità di calcolo, finora mai inserite in una GPU consumer. Le GPU Turing portate sul mercato sono enormi, con la regina di esse oltre il 50% più grande del già non piccolo GP102.
Comunque se non siete stati abbastanza colpiti dai prezzi, che è la nota dolente di questa nuova serie, sappiate che quelli riportati sono i prezzi in USA senza tasse.

Curiosamente, non è stata presentata (per ora, ma probabilmente qualche 2070Ti e 2060Ti comparirà nel futuro) alcuna scheda con GPU con unità disabilitate, metodo usato per riciclare unità non completamente funzionanti.
Spicca quindi l’anomalia di avere una GPU apposita per la serie x70 invece di usare una GPU castrata più o meno pesantemente come nelle precedenti generazioni. La cosa può essere letta come un indice di ottima resa dei die, ma nonostante ciò anche di grande costo produttivo, per cui si è preferito realizzare un die apposito per risparmiare i 100mm2 rispetto al TU104 e avere maggior margine per la serie x70 che è quella chiaramente destinata a vendere di più della terna avendo il prezzo inferiore.

Il confronto tra Turing e Pascal non è semplice: le architetture sono molto differenti con capacità diverse e dimensioni, numero di shader, TFLOPS non sovrapponibili come in precedenza per GPU che dovrebbero occupare, secondo le intenzioni di Nvdia, lo stesso segmento di mercato (da non confondere con la nomenclatura, per cui una x80 di nuova generazione non è nella posizione di mercato di una x80 della generazione precedente). La scelta è quindi caduta sul confrontare la GPU Turing che prende il posto di Pascal con prestazioni simili, quindi la GPU di classe inferiore Turing comparata con la Pascal rispettivamente di fascia superiore: il GP104 montato sulla GTX1080 e il TU106 che è montato sulla nuova RTX2070. I test condotti con vari giochi mostrano che le due GPU hanno prestazioni simili nel rendering con la rasterizzazione, con leggero vantaggio di Turing in alcuni casi.

+-------------------+--------------+---------------+----------+
| Architettura      |    Turing    |    Pascal     |          |
+-------------------+--------------+---------------+----------+
| GPU               |    TU106     |    GP104      |          |
| CUDA Cores        |     2304     |     2560      |  -10%    |
| SM                |      36      |      20       |  +80%    |
| Core Clock        | 1410/1620MHz | 1607/1733MHz  | -12%/-6% |
| Texture Units     |     144      |      160      |  -10%    |
| Tensor Cores      |     288      |       -       |    -     |
| ROPs              |      64      |       64      |    =     |
| L2 Cache          |     4MB      |      2MB      |  100%    |
| Registers (Total) |     9MB      |      5MB      |  +80%    |
| Memory Clock      | 14Gbps GDDR6 | 10Gbps GDDR5X |  +40%    |
| Memory Bus Width  |   256-bit    |   256-bit     |    =     |
| Bandwidth         |    448GB/s   |    320GB/s    |  +40%    |
| VRAM              |     8GB      |      8GB      |    =     |
| FP32 Performances |  7.5 TFLOPs  |  8.9 TFLOPs   |  -11%    |
| TDP               |  175/185W FE |     180W      |   ~=     |
| Transistor Count  |    10.8B     |     7.2B      |  +50%    |
| Die size mm2      |    445mm2    |    314mm2     |  +42%    |
+-------------------+--------------+---------------+----------+

Quindi, vediamo in dettaglio le differenze architetturali tra Pascal e Turing.

Cominciamo con la dimensione: la nuova è 131mm2 più grande della vecchia, ovvero Turing è il 42% più grande di Pascal. Nonostante le dimensioni della nuova GPU il numero di CUDA core è diminuito. Anche la frequenza nominale è diminuita (sappiamo che è comunque dinamica e che le velocità di entrambe le GPU vanno oltre 1900MHz in condizioni normali di gioco).

Parlando di numeri teorici, vediamo come la nuova RTX2070 ha 7.9TFLOPS di performance massima in FP32 contro gli 8.9TFLOPS della GTX1080, ma i test effettuati dicono che la RTX2070 ha spesso più prestazioni (misurati in FPS generati) rispetto alla GTX1080.
Più prestazioni con meno core e meno frequenza? Come è riuscita in questa impresa non certo banale?

Come evidenziato negli articoli precedenti, i numeri teorici riportati nelle specifiche non hanno alcun valore quando non sono misurati in un contesto di lavoro reale. In questo caso Nvidia ha condotto un altro piccolo passo avanti nell’aumentare quella che è l’efficienza di computazione delle nuove GPU che vanno a superare quella già elevata di Pascal. E tutto ciò sembra tramite un cambio di architettura “minimo”. Nvidia ha infatti studiato il flusso di istruzioni usati dai vari lavori che gli shader compiono e ha dichiarato che in media circa 1/3 di queste istruzioni sono di tipo integer, mentre il restante è di tipo floating point. Le istruzioni di tipo di integer sono facilmente emulate dalle unità floating point che sono più complesse. Ma eseguire così una istruzione INT semplice vuole dire non poter eseguire una istruzione FP, visto che le unità di computazione sono le stesse. Con Volta Nvidia aveva già introdotto negli SM, oltre alle classiche unità FP32, anche quelle integer (INT32) in grado di eseguire le istruzioni di questo tipo (e packed math relativa) in parallelo a quelle FP.

L’esecuzione delle istruzioni FP e INT in parallelo (con cambiamenti anche alle unità di dispatching dei singoli SM) ha permesso di aumentare l’IPC delle unità di calcolo in valore variabile a seconda della quantità di istruzioni INT usate dal codice degli shader, con una media misurata dalla stessa Nvidia del 35% circa (in aumento con le ultime versioni dei giochi rispetto a quelli più vecchi). Che non è un aumento secondario di IPC (potessero le CPU godere di tale guadagno ad ogni generazione!).

Quindi con Turing pur usando meno CUDA core e stessa frequenza i test effettuati accertano che le prestazioni sono superiori a Pascal. Ovviamente il 30% in più di IPC per i CUDA core non corrispondono direttamente a un +30% di frame generati, perché per creare un frame ci sono altre unità e processi in gioco che possono fare da collo di bottiglia. Nonostante ciò bisogna considerare che la maggiore capacità computazionale potrà essere sfruttata in futuro anche quando vi saranno altre limitazioni nel generare un più alto numero di frame.

Questo aumento di prestazioni a parità di numero di shader è un punto da tenere in considerazione anche per quello che diremo dopo.

Abbiamo già accennato alla suddivisione degli SM in blocchi più piccoli. Già con il GP100, il mega chip Pascal based destinato al mercato HPC, Nvidia aveva adottato una soluzione per cui gli SM erano in numero doppio con la metà delle ALU ciascuno. Ciò permette di avere vantaggi nell’esecuzione parallela e concorrente di più thread perché la granulosità delle decisioni viene ridotta, al costo ovviamente di più logica e quindi dimensione del die. Tale soluzione è stata usata anche per il GV100 (destinato sempre al mercato HPC) e ora la ritroviamo anche su Turing, per il mercato consumer. Vedremo dopo più in dettaglio l’impatto di questa modifica.

Il nuovo partizionamento degli SM mantiene 256KB di cache per ciascuno, per cui si ha un raddoppio di cache a parità di unità di computazione rispetto alla architettura con SM a 128 shader. Anche questo contribuisce all’aumento delle dimensioni del die.

La banda con la nuova memoria GDDR6 è aumentata dai 320GB/s della GDDR5X a 448GB/s, con un incremento relativo del 40% (in linea con l’IPC degli shader). Le TMU sono minori, quindi tutto restando come prima il texel rate puro dovrebbe essere inferiore di circa il 10% rispetto al GP104.

Ciò che non si vede dalla tabella dei numeri, è però qualcosa di più importante del conteggio delle unità di calcolo. Nvidia ha modificato lo scheduler che gestisce i thread in esecuzione aggiungendo delle risorse extra (oltre alla cache maggiorata) a ciascun SM. L’argomento vale un capitolo a se stante.

## 3.1 Presentiamo i TFLOPS

Per una maggiore comprensione dell’impatto delle modifiche di Turing è necessario capire cosa sono i TFLOPS massimi teorici che sono scritti (e talvolta sbandierati) nelle descrizioni delle varie GPU alla loro presentazione e quale reale significato hanno.

Il numero di TFLOPS (acronimo di Tera FLoating Point Operations Per Second, ovvero mille miliardi di istruzioni per secondo) teorici che sono riportati nelle specifiche indica il numero massimo di operazioni che la GPU è in grado di operare in condizioni ideali.
Queste condizioni, che sono raggiunte solo raramente durante l’elaborazione di un vero lavoro e non di un semplice benchmark atto a testare solo la quantità di operazioni eseguibili, consistono nel non considerare le inevitabili limitazioni come la banda passante per recuperare istruzioni, dati e memorizzare istruzioni e il fatto che il lavoro consista solo in una sequenza fissa di istruzioni che sono quelle che eseguono il numero massimo di operazioni per ciclo.
Nelle GPU c’è una istruzione che è in grado di eseguire una moltiplicazione e l’addizione del risultato in un accumulatore (l’istruzione FMA, Fused Multiplication and Addition). Quindi è una istruzione che esegue due operazioni (le Operations nell’acronimo TFLOPS) in un solo ciclo (attenzione, la latenza del risultato di una sola esecuzione, cioè da quanto iniziamo l’istruzione a quando abbiamo il risultato pronto non è un solo ciclo, esattamente come per ogni istruzione che viene eseguita in una pipeline. Si considera solo il fatto che se eseguiamo una serie di queste istruzioni una dietro l’altra, dopo il tempo di latenza della prima istruzione, il risultato di tutte le successive arriverà con cadenza di un ciclo).
I TFLOPS massimi, da considerare come picco assoluto, sono così calcolati sulla carta secondo una semplice formula: numero di unità di calcolo in grado di eseguire una istruzione FMA (quindi il numero di tutti gli shader) qui denominato N, moltiplicato per la frequenza di lavoro, cioè il numero di cicli in un secondo, denominata F, moltiplicato per 2, cioè le operazioni per ciclo eseguite, diviso mille miliardi (cioè 1 Tera oppure solo per un milione se si usano i MHz come unità di misura della frequenza, in modo da ridurre il numero a poche cifre significative altrimenti sarebbe davvero enorme perché le GPU al giorno d’oggi sono davvero veloci).

TFLOPS = N x F x 2 / 1000000 (con F espresso in MHz)

Nulla di complicato quindi. Esempio, per la TU108 che ha 2304 unità di calcolo che viaggiano (nominalmente) al massimo a 1620MHz, i TFLOPS massimi si calcolano:
TFLOPS = 2304 x 1620(MHz) x 2 = 7464960 / 1000000 = 7.45TFLOPS ~ i 7.5TFLOPS riportati nella tabella.

Questo numero, come detto, è un valore teorico massimo che le GPU raggiungono solo occasionalmente. Durante l’esecuzione di un algoritmo complesso in cui tra le altre cose si eseguono un gran numero di istruzioni diverse, si fa accesso contemporaneo in lettura e scrittura a più e varie parti della memoria, si demanda lavoro alle unità ad funzione fissa e si attendono sincronismi tra vari processi e sequenze di istruzioni e dati dalla CPU, e quindi il valore di operazioni eseguite al secondo è decisamente inferiore a questo numero massimo teorico ottenuto ripetendo una sequenza di soli FMA all’infinito.

Quanta è la differenza tra questi due valori dipende dalla sequenza di istruzioni, ovvero da cosa fa e come è scritto il codice da eseguire, e dalla capacità intrinseca dell’architettura (tutta) di eseguirla in maniera più o meno efficiente.
Due architetture diverse possono comportarsi in maniera differente durante l’esecuzione dello stesso tipo di lavoro, con una che ha limitazioni per una determinata istruzione o per una modalità di esecuzione o di banda passante o di quantità di cache etc.. e l’altra che ha altre limitazioni di natura diversa che la possono far comportare meglio nell’esecuzione di un determinato lavoro e peggio in un altro.

Due architetture che hanno due valori di TFLOPS massimi uguali possono dunque avere prestazioni diverse nello svolgere un determinato lavoro. Quanto più alte sono le prestazioni di una architettura nell’eseguire tale lavoro rispetto al valore massimo di TFLOPS che le è proprio, migliore è la sua efficienza computazionale nello svolgere quel compito. Corollario di questo è che maggiore la sua efficienza, minore il valore di TFLOPS massimi teorici necessari per eseguire lo stesso lavoro nello stesso tempo di un’altra architettura che invece ha TFLOPS teorici maggiori.

Ovviamente la valutazione ha senso quando ad essere misurato è un lavoro complesso e con un senso che non sia un benchmark specifico di una sola funzionalità, quindi misurare gli FPS generati in un gioco o il tempo necessario per eseguire un algoritmo di computazione complesso e completo (quindi dal dato grezzo al risultato finale che abbia un senso, non per esempio solo il tempo di esecuzione dell’istruzione FMA ripetuta all’infinito come visto prima), ovvero comparando misurazioni di qualsiasi cosa per cui la costante di efficienza non sia posta a 1 come ipotesi necessaria dal test stesso.

Ora che sappiamo cosa significa il valore di TFLOPS riportato nelle specifiche di una GPU, possiamo cercare di capire se e come è migliorata una architettura rispetto ad un’altra. Cominciamo con la valutazione generale dei risultati, poi vediamo in dettaglio altre differenze più specifiche.

Comparando Turing con Pascal si hanno meno TFLOPS teorici per il primo ma prestazioni uguali o maggiori rispetto al secondo (secondo i vari test eseguiti dai siti di benchmarking sparsi per il mondo), quindi maggiore efficienza computazionale del primo rispetto al secondo valutabile, secondo la tabella sopra in (8.9-7.5)/7.5 = 18% circa. Ecco quindi che meno unità e meno frequenza possono portare ad avere le stesse (o anche migliori) prestazioni.
Il tutto anche con una maggiore efficienza sui consumi dato che Turing a parità di lavoro (eseguibile efficientemente anche su Pascal) consuma dal 15 al 20% in meno, in perfetta coerenza con la maggiore efficienza computazionale. Per lavori in cui anche le nuove unità di Turing sono usate, le differenze a favore di questi diventano maggiori, ovviamente.

Aneddoto storico: mi è capitato tempo fa di leggere una comparazione tra architetture in si faceva riferimento al calcolo dei TFLOPS massimi teorici per confrontare i miglioramenti architetturali tra Maxwell e Pascal. Moltiplicando il numero di unità di calcolo x frequenza x 2 il risultato era che entrambe le architetture avevano gli stessi TFLOPS teorici e quindi si era concluso che le due architetture avessero le stesse caratteristiche senza nessun miglioramento della seconda sulla prima.
E’ chiaro che semplicemente comparare i TFLOPS massimi di architetture diverse per capire le prestazioni relative è sbagliato e tanto più quando si sbaglia a comprendere cosa si sta misurando.

## 3.2 Async Computing, finalmente?

Sappiamo che con le DX12 è stato introdotto una feature particolare che è stata chiamata “Asynchronous Computing” il cui scopo è di eseguire con più efficienza un numero maggiore di thread contemporaneamente (sarebbe meglio dire in concorrenza) permettendo in teoria di aumentare le prestazioni sfruttando meglio le unità computazionali che altrimenti rimarrebbero inutilizzate in alcuni frangenti. Come accennato prima, alcune architetture sembrano soffrire di una creazione di questi stalli sempre più importante man mano che il numero di unità di elaborazione aumenta inficiando le effettive capacità di computazione che si allontanano sempre più da quel limite teorico che è riportato in tabella.

PIC_32

Le DX12 prevedono l’accodamento di differenti tipi di lavori che poi possono o meno essere eseguiti in maniera parallela o concorrente e/o asincrona nel modo che più riesce ad essere efficiente sull’architettura che li elabora.
La modalità di gestione è quindi implementato a livello HW in maniera completamente diversa in ogni architettura. O può persino non essere implementato. Il supporto o meno all’Async Computing non cambia le feature messe a disposizione per elaborare una immagine (che alla fine avrà la stessa qualità), ma solo il modo e i tempi (che è ciò che importa) con cui queste elaborazioni sono eseguite. Architetture diverse possono richiedere metodi differenti di gestione dei thread per migliorare le prestazioni assolute o per un migliore compromesso transistor/consumi/prestazioni o non sfruttare questa opportunità e implementare aumenti prestazionali in altri modi.
Lo scopo dell’Async Computing è dunque rendere disponibile uno strumento ulteriore per aumentare le prestazioni senza che sia imposto in alcun modo il come debba essere usato.
L’Async Computing è arrivato alla ribalta delle cronache secondo la modalità implementata da AMD nella sua architettura GCN.
Questa architettura ha mostrato di avere dei problemi di inefficienza nell’assegnare il lavoro di pochi thread alle unità di elaborazione man mano che in loro numero aumenta, al punto che con le DX11 che usano appunto pochi thread per compiere il lavoro di rendering dell’immagine le prestazioni sono decisamente più basse rispetto alle architetture della concorrenza che invece riescono a trarre maggior profitto da questo tipo di lavori. La soluzione al problema da parte di AMD è stata la creazione di questa feature per le DX12 e la sua implementazione simile al meccanismo di Hyper Threading presente sulle CPU, dove il secondo thread occupa gli stalli della pipeline che il primo thread ha durante la sua esecuzione, portando quindi l’uso delle ALU più vicine al 100% (ovvero più vicine a raggiungere il valore di TFLOPS teorici indicati nelle tabelle). Per fare ciò AMD ha introdotto delle unità speciali, chiamate ACE, che sono esterne agli Shader Engine e in numero variabile tra revisione e revisione dell’architettura e che determinano quali thread eseguire su quali CU, eseguono il preemption dei task se e quando necessario e che usano diverso spazio sul die per le cache di context switching. La tecnica è raffinata ed effettivamente consente di aumentare le prestazioni rispetto alle DX11, ma per sfruttare in maniera adeguata questa sovrastruttura alle unità di calcolo vere e proprie è necessario che i programmatori suddividano in maniera esplicita e sistematica il lavoro da svolgere e permettere quindi, tramite maggiore concorrenzialità di esecuzione, di sfruttare al massimo i tempi morti delle unità di calcolo.
Sebbene come detto il meccanismo sia irreprensibile dal punto di vista funzionale, nella realtà si scontra con un rapporto risorse/lavoro aggiuntivo/prestazioni che va valutato più attentamente: i vari test dei giochi mostrano infatti che, a parte l’esecuzione di test ad hoc che fanno solo una cosa ben precisa, il guadagno reale si attesta al massimo al 20% in più di prestazioni. Ci si chiede allora se tale guadagno non sia possibile attraverso altri metodi, come per esempio ridurre il numero o la durata degli stalli prodotti nell’elaborazione. Come abbiamo visto, già solo l’introduzione di una unità di esecuzione INT ha aumentato l’IPC di oltre il 30%, e questo guadagno non richiede alcun lavoro aggiuntivo ai programmatori, nessuna spezzettatura manuale di lavori (dividere lavori in sotto problemi indipendenti non è sempre così banale) se non quella di sfruttare le operazioni integer ogni volta che è possibile al posto di quelle FP (e qui può venire in aiuto un compilatore che fa il lavoro in maniera automatica).
Nvidia non ha unità equivalenti agli ACE nelle sue architetture e non si avvantaggia in maniera così estrema dell’uso del context switching tra thread in stallo per saturare le proprie unità di calcolo che sono decisamente più efficienti rispetto alla architettura AMD sotto questo punto di vista. Perché la tecnica della sostituzione del thread in elaborazione quando in stallo abbia effetto positivo sulle prestazioni richiede che il tempo di context switching sia inferiore al tempo di stallo. Nell’architettura Nvidia gli stalli sono molto brevi ed inoltre il context switching richiede parecchio tempo perché i dati sono memorizzati direttamente nella VRAM e non in cache dedicate. Ne deriva automaticamente che la tecnica usata da AMD non ha le stesse proprietà benefiche per le architetture Nvidia, che anzi possono soffrire, come Maxwell.
Nvidia quindi non ha mai abbracciato l’uso dell’Async Computing come un dogma necessario affinché le sue architetture lavorassero al meglio, sebbene diversamente da quanto è stato affermato da molti su nessuna base conoscitiva, le sue architetture lavorano perfettamente in parallelismo, possono fare context switching, lavorano in concorrenza e anche anche in asincronia (concetti diversi che il termine Async Computing ha un po’ messo in confusione) e hanno uno scheduler HW (con più o meno limitazioni a seconda dell’architettura). Per chiarire tutti questi concetti serve una base di programmazione e qui non verranno spiegati, si voleva solo chiarire che il termine Async Computing nasconde dietro di se diverse nozioni che non sono conosciute a tutti quelli che ne parlano liberamente sui forum, quindi diffidate sempre dalle informazioni date a cuor leggero che leggete nei forum. Se non conoscete le regole dell’hockey su ghiaccio ma sentite uno che dice che per tale sport bisogna colpire la palla al volo con al massimo 3 tocchi e passare solo al compagno che sta dietro al disco e voi prendete per buono quello che viene detto, ve ne andrete via con un bel problema a capire come si gioca ad Hockey e riportare le stesse regole a chi lo pratica diventa imbarazzante, di più ancora se vi ostinate a cercare di avere ragione. E di cose imbarazzanti ne ho lette diverse dal lancio delle DX12 a oggi un po’ su tutti i temi, compresa l’assurdità che se non sei Async Computing Comptibile (nel senso che non implementi la stessa tecnica di gestione dei thread di AMD dove come detto è l’unica a trarne beneficio in tal maniera) non sei DX12 compatibile. La compatibilità con l’Async Computing infatti richiede un’altra cosa ben più semplice (semplice esposizione di 3 code per i tre tipi di lavori che possono essere accodati) e non è neppure resa obbligatoria dalle specifiche DX12.

Tornando alle nostre GPU, le DX12 e le librerie Vulkan sono sfruttate ampiamente sulle console (rispettivamente sulla XBoX e sulla PS4) dove l’uso di molti thread lanciati dalle unità ACE permette alle GPU di questi dispositivi (tutte basate su architettura GNC) di sfruttare meglio le risorse di calcolo a disposizione.
Purtroppo però questa tecnica di programmazione non si è mai sposata bene con il metodo di gestione più semplice dei thread di Nvidia (che sono gestiti anche loro da uno scheduler HW con strategie diverse da quelli AMD). Il metodo di organizzazione del lavoro da svolgere in decine di thread separati non è né la migliore né è necessaria secondo i dettami delle DX12 né tanto meno è richiesto il supporto ad un task switching “frenetico” con supporto di HW specifico come necessita l’architettura GCN per colmare gli stalli che si formano nelle sue CU.
Senza entrare nei dettagli, Nvidia che ha sempre supportato via HW sia la concorrenzialità dei thread, sia il task switching tra le diverse code anche senza gli ACE (come detto il task switching di Nvidia è molto più lento di quello AMD, da qui il problema dell’uso dell’AC come inteso da AMD), dopo essere partita con una gestione di tali feature molto poco flessibile con Maxwell (scheduling dei thread solo alla conclusione del thread grafico, ovvero ad ogni frame), ha migliorato con Pascal (con il Dynamic Load Balancing, con scheduling dinamico a livello di wavefront ma con task switching sempre molto lento) e ha ulteriormente aumentato la flessibilità delle gestione con Turing come vedremo.
Ancora però non è presente alcuna unità ACE dedicata alla gestione dei thread (come sostenuto da qualcuno che non ha bene idea di cosa siano gli ACE, dove lavorano e che funzione svolgono), ma il front end di ogni SM ha guadagnato una serie di modifiche per cui ora il task switching è un’ordine di grandezza più veloce (al pari di quanto fa GCN) e la gestione della concorrenzialità dei thread è aumentata (o meglio scesa nella pila di gestione) a livello di singolo thread invece che di gruppo (wavefront). Insieme alla suddivisione dell’SM in due gruppi indipendenti di unità di calcolo, quindi con il raddoppio degli scheduler HW oltre che dei dispatcher per una strategia di concorrenza più finemente granulare, Turing riesce a supportare il carico maggiore di thread che i motori ottimizzati per console (quindi GCN) creano.
Quindi contrariamente a quanto affermato da qualcuno che non ha ben presente cosa è la funzionalità di Async Computing, non c’è in Turing un supporto a questa feature che prima non c’era (e che faceva affermare che ciò rendeva le architetture Nvidia non pienamente DX12 compatibili): il supporto c’è ora come prima, solo che la flessibilità è aumentata al punto tale che il vantaggio che AMD aveva con l’uso degli ACE è sparito, sembra, completamente. Questo ha implicazioni non secondarie, visto che insieme al già citato aumento di efficienza computazionale porta Turing ad essere qualcosa di ultra competitivo anche senza l’uso delle nuove unità di calcolo (Tensor e RT) sfruttabili per altri carichi di lavoro. E Nvidia non ha dovuto aggiungere ulteriori unità dedicate nell’uncore anche per l’AC come ha fatto AMD (anche se ovviamente 2 nuovi moduli SM con il conseguente raddoppio della cache occupano in proporzione più spazio rispetto a quello unico precedente).
Con Turing quindi Nvidia ha colmato uno degli handicap che la caratterizzava in negativo rispetto ad AMD che ha ideato e voluto inserire questa funzionalità a meglio supportare il proprio HW.

## 3.3 Le nuove unità di calcolo

Le restanti nuove unità in Turing non hanno impatto sulle prestazioni dei giochi che sono stati sviluppati fino ad oggi. Sono unità dedicate per nuove funzionalità, tra cui il sopra citato ray tracing e una nuova modalità di filtraggio alternativa ai classici metodi anti aliasing, il DLSS (Deep Learning Super Sampling) che sfrutta tecniche di Deep Learning per creare immagini di qualità superiore partendo da immagini a bassa risoluzione. Anticipiamo che il Deep Learning come tecnica di apprendimento è effettuata sui server Nvidia offline, elaborando in anticipo rispetto al rilascio la grafica del gioco, e che poi i risultati di questi calcoli (che sono continuamente aggiornati con allenamento di nuovi sample) sono distribuiti come pacchetti aggiuntivi per i giochi che supportano tale caratteristica.
Nella affermazioni di Nvidia permette quindi di eseguire un rendering a risoluzione bassa ma ottenere una qualità finale di immagine simile a quella di maggior risoluzione. Utile per esempio avere prestazioni 4K (che è la moda del momento) su schede che altrimenti non ci arriverebbero con prestazioni decenti.
Per ora quindi sono unità che “consumano transistor”, che paghiamo (caro) ma che non hanno alcuna reale funzione con i giochi usciti finora e di cui molti parlano avere prestazioni insufficienti per realizzare scene in ray tracing a questa o quest’altra risoluzione con questa o quest’altra velocità di aggiornamento.
In verità quale prestazioni attendersi con l’uso di queste nuove unità con il sospirato ray tracing real time non è davvero possibile definirlo.
L’uso del ray tracing nei moderni motori di rendering è una aggiunta alla classica pipeline di rasterizzazione che come abbiamo già detto si è evoluta dai tempi delle Voodoo. Per ora, anche secondo le parole di Nvidia, le prestazioni non sono tali da permettere di creare una intera scena in real time se non a risoluzioni molto basse. Per cui il ray tracing può essere usato per creare solo effetti in zone limitate della scena (quelle dove come abbiamo detto l’uso delle tecniche tradizionali porterebbe più problemi ed effetti collaterali che ad usare questa tecnica computazionalmente costosa) o per operazioni in background slegate dalla effettiva risoluzione in uso.
Quello che non viene considerata nelle varie discussioni sulle possibilità di queste unità di calcolo (che sono variabili in numero tra le varie fasce della serie 2000 proposte da Nvidia) è la qualità dell’immagine risultate dal ray tracing. In teoria, ed è già stato fatto in pratica, è possibile generare tramite ray tracing una immagine a basso dettaglio (da non confondersi esclusivamente con bassa risoluzione) in real time. Effetti come riflessioni, rifrazioni e occlusioni, quindi tutti gli effetti che il ray tracing simula in maniera “naturale”, possono essere resi con una qualità diversa a seconda della quantità di risorse di calcolo che si vogliono (o si possono) utilizzare senza dover ricorrere a trucchi e azioni di correzione o con la necessità di ottimizzazioni ad hoc per evitare effetti collaterali inaspettati per le limitazioni della pipeline di rasterizzazione.
Senza entrare troppo nei dettagli, i tensor core usati per il ray tracing servono proprio per questo. La qualità dell’immagine finale di un processo di ray tracing dipende dal numero (e durata) dei raggi che si vogliono simulare per ciascun pixel sullo schermo. A meno di non usare un numero pressoché infinito di questi raggi (riducendo a zero le prestazioni anche di un super server dedicato a questo lavoro) il risultato sarà un mosaico di punti più o meno denso che sarà però abbastanza lontano qualitativamente da una immagine foto realistica. Serve l’applicazione di una serie di filtri che omogenizzi i risultati in modo che questo mosaico all’apparenza molto impreciso, si possa “spalmare” su una superficie più o meno grande e renderla uniforme diminuendone il rumore.
Quanto questa uniformità si possa ottenere da un numero di punti è proprio quanta qualità si vuole ottenere dall’applicazione dell’algoritmo di ray tracing. Minore il numero di punti (raggi) elaborati, minore il tempo di calcolo, maggiore il numero di immagini al secondo prodotte ma maggiore il peso del filtro per uniformare l’immagine finale con conseguente minore qualità (perdite di dettaglio).
Dire quindi quanti frame al secondo saranno possibili a una determinata risoluzione per un determinato effetto non è possibile stabilirlo a priori se non considerando anche la qualità dell’immagine che si vuole ottenere. Per fare una analogia è come se si volesse giocare alla risoluzione 4K con qualità ultra low perché la scheda non permette di sostenere il 4K con una qualità high.
Il gioco girerà a 4K a 60FPS, ma la qualità dell’immagine ne risentirebbe e quindi il compromesso tra velocità e qualità va valutato. Molti sostengono che basta loro giocare in 4K con la qualità di certi effetti ridotta per raggiungere un frame rate accettabile, ed altri che se non “maxano” a 120FPS costanti non considerano nemmeno poter definire il gioco giocabile a tale risoluzione. Ci sono quindi pesi e misure diversi a seconda di cosa si vuole ottenere.

## 3.4 Quale uso per queste unità (e i loro costi)?

Fatto salvo che l’uso degli algoritmi di ray tracing per ogni cosa sono il desiderio recondito di ogni motore di rendering e quindi l’evoluzione ci porterà sempre più a dimenticare le tecniche classiche realizzate tramite unità fixed function ed elaborati effetti realizzati tramite lunghi ed innumerevoli shader, le prestazioni che Nvidia oggi pubblicizza per le Turing potrebbero essere sufficienti per generare alcuni effetti grafici che sono migliori di quelli creati tramite trucchi e pre-condizionamenti / limiti e pre-calcoli come sono ad esempio quelli necessari per:
– illuminazione globale, che è sempre stato uno dei maggiori problemi perché definisce l’intensità e qualità delle ombre
– le ombre, oggi calcolate tramite diversi sofisticatissimi trucchi che richiedono parecchia capacità di elaborazione pur non garantendo qualità decenti e resa finale realistica. Usare le unità RT per calcolarle dovrebbe permettere di diminuire il carico di lavoro degli shader e quindi essere meno shader constrained, permettendo così di aumentare il frame rate anche su schede con minore quantità di capacità di calcolo FP32.
– gli highlights, che sono le zone di riflessione massima della luce verso la telecamera oggi simulati tramite light map e applicazione multipla di texture
– ambient occlusion che andrebbe a sostituire quelle tecniche come SSAO o HBAO
– effetti di trasparenza, oggi un delirio di complessità e artefatti da gestire tramite rasterizzazione
– in generale aumento della qualità grazie alla possibilità di avere effetti “gratuitamente” (con sufficiente numero di unità RT) di trasparenza, riflessione, rifrazione e anche caustica (pensiamo alla simulazione delle superfici d’acqua per esempio).
Ma le stesse unità possono essere usate anche:
– Intelligenza artificiale per creare nemici che non si comportano solo seguendo scripts predefiniti per quanto evoluti e complessi questi possano essere. Quindi intelligenze che possono evolversi e magari imparare anche da dati inviati on line da tutti i giocatori che permetterebbero di creare IA in grado di dare del filo da torcere ache a chi normalmente con la pratica diventa un maestro in un determinato gioco (normalmente imparando i punti deboli dell’IA sciptata).
– IA che gioca per davvero alla pari, senza usare trucchetti e dati che ai giocatori umani non sono dati conoscere (classico l’esempio in molti giochi di essere continuamente presi di mira anche quando ci si sposta nascosti… credete che lo script che gestisce l’IA del nemico calcoli se voi siete visibili o meno facendo ray casting della vostra sagoma contro il riparo dietro cui vi siete nascosti o vi tracci semplicemente per distanza dopo che siete stati individuati?)
o nei giochi strategici che “sbircia” attraverso la Fog Of War a voi invece impenetrabile.
– Path finding, per migliorare (insieme alla IA), i percorsi che le unità non controllate possono trovare per spostarsi e interagire.
L’uso di queste unità di calcolo per realizzare effetti più complessi, come riflessioni, trasparenze e fonti di luce visibili sono quindi solo una parte delle loro possibilità. Certo, sono quelle che maggiormente piacciono al videogiocatore che si ferma alla spettacolarità dell’immagine (effetto WOW), ma come detto, ci sono molti altri aspetti della qualità d’immagine migliorabili anche senza che vi sia una sola riflessione calcolata su una vetrata o pavimento di marmo super lucido come nelle demo dove tutto è esasperato per mostrare la meraviglia della novità.
Possibilmente con la speranza di farlo anche senza avere una quantità enorme di capacità di calcolo necessarie per realizzare semplici effetti o, come si vorrà arrivare nel futuro, necessariamente solo quando si potrà creare l’intera scena esclusivamente con gli algoritmi di ray tracing.

Con l’arrivo delle nuove unità di calcolo che si affiancano a quelle tradizionali FP32, viene meno il significato dei TFLOPS che abbiamo visto precedentemente. Le capacità di calcolo delle nuove GPU sono ora così diversificate che Nvidia ha creato un nuovo metodo per la loro misurazione.
Non più quindi solo il mero numero teorico espresso in TFLOPS, ma un indice che tiene conto anche delle altre capacità, così espresso:

PIC_33

La slide mostra anche il valore di TFLOPS generato dalle unità FP32 che Nvidia ritiene necessario per gestire un miliardo di raggi ray tracing (Giga Ray) pari a 10 TFLOPS. Con le vecchie schede top gamma che superano di poco questo valore, quindi capaci di circa un GigaRay, e con il TU102 che Nvidia dice essere in grado di gestire 10 GigaRay, possiamo stimare che l’accelerazione che le nuove unità RT producono nel calcolo di algoritmi ray tracing è di un ordine di grandezza (10 volte tanto). TU104 e TU106 hanno rispettivamente capacità di 8 e 6 GigaRay.

## 3.5 Quanto costa il ray tracing

Avendo Nvidia deciso di creare delle GPU enormi perché impossibilitata dal ridurre le dimensioni per mancanza di un nuovo processo produttivo adeguato e comunque volendo rendere disponibile le nuove funzionalità, il prezzo di queste nuove GPU è davvero molto alto.
Le nuove schede infatti, oltre che a pagare il solito scotto di essere nuove e le più veloci del mercato che già innalza i prezzi di suo, sono anche prodotte con diversi mm2 che costano. Difficile credere che le rese di queste GPU siano in linea con quelle Pascal della generazione precedente ed è quindi normale che siano vendute a prezzo decisamente più alto indipendentemente da quale siano le loro effettive prestazioni rispetto alla generazione che vanno a sostituire.
D’altronde come detto, non hanno solo quelle prestazioni con i giochi di oggi, ma promettono anche di usare il ray tracing e nuove funzionalità quando i nuovi motori cominceranno a sfruttare le nuove unità di calcolo sempre di più (e meglio) e il DLSS man mano che sempre più giochi ne faranno uso.
Detto questo, i prezzi di lancio delle nuove schede sono decisamente fuori portata per molti e sono destinate solo alla fascia più enthusiast del mercato, lasciando a Pascal il compito di continuare a soddisfare le necessità di coloro che non possono permettersi tale cifre e di contrastare la residua concorrenza nelle fasce più basse ai prezzi (già comunque alti) della passata generazione.

Press ESC to close