Adaptive Bucket Splitting: il rendering con V-Ray non sarà più lo stesso
Con l’ultimo aggiornamento hotfix di V-Ray per 3ds Max il bucket rendering sarà molto più veloce delle precedenti release. Grazie al nuovo algoritmo intelligente, Chaos ha risolto uno storico “problema” di calcolo, per la gioia di tutti i 3D artist!
Però il rendering in bucket porta con sé un problema ben noto: la cosiddetta “Sindrome dell’ultimo Bucket”!
Riprendendo la splendida analisi di Emanuele Lecchi nel suo articolo sul sito Chaos Group, oggi voglio parlarti della grandissima rivoluzione rilasciata per tutti gli utenti di V-Ray per 3ds Max: l’Adaptive Bucket Splitting.
Facciamo un quadro generale
Distribuire la mole di lavoro sui singoli Thread del processore, quando si ha a che fare con una mole di calcolo non indifferente, ci porta dritti a scontrarci con un problema teorico ricorrente nel mondo della computer grafica moderna, e non solo in termini di rendering.
Ogni Bucket (per chi non lo sapesse, parliamo di ogni singolo quadratino colorato rappresentato nell’immagine di copertina) è un “nodo” di calcolo attribuito ad un rispettivo Thread della CPU. Avvicinandoci alla chiusura dell’ elaborazione dell’immagine, ci troviamo di fronte ad una fase critica in cui i bucket in elaborazione risulteranno essere minori dei Thread disponibili della CPU.
Questo comporta l’aumento proporzionale di Thread inattivi man mano che ci avviciniamo all’ultimazione della scena, e quindi ci troveremo ad avere il processore che risulterà essere man mano più “scarico di lavoro”, rallentando l’elaborazione invece che accelerarla.
La “sindrome” che ti ho nominato all’inizio deriva appunto da questa procedura: un’immagine elaborata in bucket dovrà per sua definizione chiudersi con un singolo bucket al lavoro e, di conseguenza, con un singolo thread che calcola arditamente mentre tutti gli altri sono a braccia conserte che lo attendono. In moltissimi casi è possibile trovarsi col singolo bucket che, da solo, richiede un tempo di calcolo pari al resto dell’immagine.
Purtroppo questo è uno scenario molto comune dato che solitamente un’immagine non è mai omogena nel suo sviluppo planare: un cielo limpido infatti sarà calcolato in modo rapido rispetto ad prato applicato in scattering sul terreno. L’unica certezza in ogni singolo render è che ci sarà un’ area più ostinata delle altre causata o dalla richiesta di elaborazione per raggiungere la soglia di rumore richiesta, oppure da un piccolo colpo di luce speculare.
Negli anni sono state sviluppate diverse soluzioni a questo fastidioso problema. A partire dalla cura nella configurazione della scena o della sua gestione, fino alla gestione del codice – ad esempio riducendo le dimensioni dei bucket man mano che ci si avvicina alla fine – il ventaglio di soluzioni ideate non ha mai portato ad una vera risoluzione del problema.
Nessuno di questi approcci infatti ha potuto eliminare definitivamente la perdita di efficienza del rendering in bucket in particolare quando ci si avvicina alla fine del rendering stesso, riportando tutte inevitabilmente al fastidioso bucket bloccato nel tempo e nello spazio.
I vari suggerimenti
E di possibili strategie di risoluzione ne sono arrivate davvero tante.
Rimpicciolire i bucket
Questo approccio da un lato aiuterebbe i moderni processori multi-core a sprigionare tutta la loro potenza di calcolo, ma dall’altro lato finirebbe per costare di più in altri termini. Il bordo di due bucket contigui viene infatti calcolato due volte, prima da un thread e poi dall’altro.
Giocoforza avere un numero maggiore di bucket, benché siano di dimensioni ridotte, comporterebbe più bordi e quindi più bordi da calcolare. Quindi ciò non porterebbe nessun vantaggio sull’ultimo bucket bloccato.
Mouse follow
Oltretutto questa proposta non è affatto sostenibile con scene animate o con nuove immagini dove il contenuto o la preview non è ancora nota.
Threshold splitting
Questo aiuta a mantenere alta l’occupazione del core, ma purtroppo non risulta adeguata con immagini molto disomogenee dove può capitare che un grande bucket iniziale può rimanere bloccato per più tempo rispetto ai bucket più piccoli che vanno per la loro strada verso il completamento.
Impiegare la Light Cache
Sfortunatamente è stato dimostrato che l’impiego dei prepass definiti dalla Light Cache per capire in anticipo quali aree dell’immagine richiedano più tempo non è proprio il massimo dell’ottimizzazione: il campionamento infatti non è sufficientemente alto e perciò non si otterrebbe una rappresentazione dell’immagine abbastanza fedele per poter fare delle scelte in anticipo.
Riavvio forzato dei bucket bloccati
Anche questa soluzione purtroppo non si è rivelata ideale, poiché i campioni già coinvolti verrebbero annullati in qualche punto arbitrario e non ben definito, col rischio di attivare il processo in un punto sbagliato della scena e col potenziale allungamento dei tempi di rendering, specialmente con un bucket bloccato nell’ elaborazione di una porzione finale della scena.
Questa possibile soluzione è stata valutata in diverse varianti, ma sfortunatamente nessuna di loro ha portato alla risoluzione del problema risultando non ottimale in una o più situazioni.
Utilizzo di fotogrammi precedenti
Sfortunatamente, anche in questo caso, la soluzione non era dietro l’angolo e non c’è stata alcuna evidenza palese di efficacia. Infatti in molte produzioni non è possibile garantire continuità tra i fotogrammi: nuove aree difficili da renderizzare potrebbero entrare nel campo visivo in un fotogramma e scomparire nel seguente, perciò potrebbe diventare impossibile -se non inutile- utilizzare i frame precedenti come base per il precalcolo.
La soluzione
Così facendo è stato possibile realizzare un’intelligenza artificiale che permette quindi di ottenere uno Splitting Adattivo del Bucket.
Ma cosa vuol dire a tutti gli effetti?
Quando un thread rimane scarico di lavoro, viene forzato ad aiutare gli altri thread ancora indaffarati nell’elaborazione.
Il bucket verrà quindi diviso, e tutto il campionamento completato dal thread originale non verrà annullato, ma trasferito e condiviso col nuovo thread di supporto, in modo che nessuna fase di campionatura venga persa. Così facendo, il thread di supporto, ha un punto di partenza ben chiaro da cui far partire la convergenza verso il risultato finale.
Questa divisione non è però svolta in maniera casuale: infatti la nuova intelligenza artificiale si attiverà in base a quanti thread inattivi sono disponibili e, ovviamente, alla porzione di immagine che è rimasta da renderizzare.
E la vera svolta sai qual è?
È che ora è possibile splittare il singolo bucket fino alla dimensione di un pixel agevolando il tutto, poiché anche l’area all’interno di un singolo bucket è affetta da discontinuità e quindi ci saranno pixel che richiedono meno potenza di elaborazione e altre che ne richiedono di più.
I veri benefici del bucket splitting
Ma non solo: poiché la divisione avviene solo in presenza di thread inattivi, l’accelerazione dell’elaborazione avviene esattamente nel momento ideale, ossia nel momento in cui un thread è più in affanno rispetto ad altri scarichi.
Questa soluzione inoltre si è rivelata versatile in più situazioni (compreso l’animazione) poiché la suddivisione del bucket avviene senza l’impiego di un’immagine/frame o precalcolo immagazzinato nella cache, e quindi senza la necessità di avere un’immagine grezza renderizzata in partenza: questa tecnica si rivela ottimale nella condivisione del carico di lavoro indipendentemente dal contenuto della scena, o dal tempo già speso per il rendering.
Il concetto alla base è relativamente semplice: finché ci saranno thread liberi e pixel da calcolare, ogni parte del processore verrà messa al lavoro.
Così facendo si ottiene una generale e diffusa diminuzione dei tempi di rendering, che ovviamente rimarranno dipendenti dalla complessità della scena e dal numero di core (e thread) disponibili sulla tua CPU.
I limiti riscontrati
Tradotto in parole semplici se, per pura casualità, la parte che richiede più tempo di elaborazione è un singolo pixel, rimarrà comunque un singolo thread a lavorare per l’ultimazione dell’immagine. Il bucket bloccato però avrà dimensione di un singolo pixel e non di centinaia o migliaia, ma comunque non verrà annullata la potenziale richiesta di ulteriore tempo di calcolo.
Questo approccio specifico è attualmente applicabile solo in rendering locale e non può essere ad ora attuato su sistemi di rendering distribuito e/o con render farm, poiché ciò richiederebbe un approccio leggermente diverso e che sia in grado di assicurare un traffico di rete basso.
Nel caso te lo stessi chiedendo, la ricerca è attualmente in corso per la risoluzione di questi problemi residui.
Cambiamenti nei flussi di lavoro
Nel caso di Region Rendering, non c’è bisogno di cambiare le dimensioni dei bucket per farli rientrare all’interno di una singola regione, mentre il mouse follow dividerà in modo del tutto automatico qualsiasi bucket rimanente, annullando totalmente la necessità di interazione dell’utente finale.
Oltretutto questa tecnica permetterà l’utilizzo di bucket più grandi e li manterrà più a lungo rispetto al precedente metodo di divisione.
Bisogna fare però attenzione a non scegliere una dimensione iniziale dei bucket troppo grande, poiché questo potrebbe causare altri inconvenienti. In sostanza, quindi, non c’è bisogno di scegliere piccole dimensioni dei bucket per completare l’immagine in modo più rapido ed efficiente: il nuovo algoritmo si autoregolerà in autonomia in base alle dimensioni predefinite (o più grandi).
Come da corollario, i ben noti problemi di campionamento della Profondità di Campo (DOF) o del Motion Blur saranno notevolmente migliorati (benchè i bucket piccoli abbiano comunque una maggior probabilità di perdere campioni).
Come ottenerlo?
In ogni caso questo algoritmo verrà esteso a tutte le altre integrazioni DCC.
Se non disponi di una licenza di V-Ray 5 puoi ottenerla rapidamente accedendo al nostro shop cliccando qui oppure puoi contattarci in qualsiasi momento per avere maggiori informazioni.
Lascia un commento