Perché la ricorsione è vietata in OpenCL?


19

Vorrei usare OpenCL per accelerare il rendering delle immagini raytracing, ma noto che la pagina di Wikipedia afferma che la ricorsione è vietata in Open CL. È vero? Dato che faccio largo uso della ricorsione durante il raytracing, ciò richiederà una considerevole quantità di riprogettazione per beneficiare dell'accelerazione. Qual è la restrizione sottostante che impedisce la ricorsione? C'è un modo per aggirarlo?


2
Le GPU funzionano in modo diverso. (Alcune architetture) non hanno il concetto di uno "stack di programma" globale, quindi in queste non è possibile effettuare chiamate ricorsive. OpenCL probabilmente adotta il minimo comune denominatore, impedendo così completamente di rimanere portatile tra le GPU. Più recente hardware CUDA sembra aver introdotto il supporto per la ricorsione a un certo punto: stackoverflow.com/q/3644809/1198654
glampert

Risposte:


27

È essenzialmente perché non tutte le GPU possono supportare le chiamate di funzione e, anche se possono, le chiamate di funzione possono essere piuttosto lente o avere limitazioni come una profondità dello stack molto ridotta.

Il codice shader e il codice di calcolo della GPU possono sembrare avere chiamate di funzione in tutto il luogo, ma in circostanze normali sono tutte inserite al 100% dal compilatore. Il codice macchina eseguito dalla GPU contiene rami e loop, ma nessuna chiamata di funzione. Tuttavia, le chiamate di funzione ricorsive non possono essere integrate per ovvie ragioni. (A meno che alcuni degli argomenti non siano costanti tempo di compilazione, in modo tale che il compilatore possa piegarli e incorporare l'intero albero delle chiamate.)

Per implementare vere chiamate di funzione, è necessario uno stack. Il più delle volte, il codice shader non utilizza affatto uno stack: le GPU hanno file di registro di grandi dimensioni e gli shader possono mantenere tutti i loro dati nei registri per tutto il tempo. È difficile far funzionare uno stack perché (a) avresti bisogno di molto spazio nello stack per fornire tutti i numerosi orditi che possono essere in volo contemporaneamente, e (b) il sistema di memoria GPU è ottimizzato per raggruppare molto insieme delle transazioni di memoria per raggiungere un throughput elevato, ma ciò comporta spese a causa della latenza, quindi la mia ipotesi è che le operazioni dello stack come il salvataggio / ripristino delle variabili locali sarebbero terribilmente lente.

Storicamente, le chiamate di funzione a livello hardware non sono state troppo utili sulla GPU, poiché ha più senso incorporare tutto nel compilatore. Quindi gli architetti della GPU non si sono concentrati sul renderli veloci. Probabilmente potrebbero essere fatti alcuni diversi compromessi, se in futuro vi sarà una richiesta di chiamate efficienti a livello di hardware, ma (come per tutto ciò che riguarda l'ingegneria), ciò comporterà un costo altrove.

Per quanto riguarda il raytracing, il modo in cui le persone di solito gestiscono questo genere di cose è creando code di raggi che stanno per essere rintracciati. Invece di ricorrere, aggiungi un raggio a una coda e ad alto livello da qualche parte hai un ciclo che continua l'elaborazione fino a quando tutte le code sono vuote. Tuttavia, richiede una riorganizzazione significativa del codice di rendering se si parte da un classico raytracer ricorsivo. Per ulteriori informazioni, un buon documento da leggere al riguardo è Wavefront Path Tracing .


6
Sono riluttante a condividere questa salsa segreta, ma ho avuto abbastanza fortuna di avere un numero di rimbalzi massimo fisso e di avere una pila di dimensioni fisse (e un ciclo con un numero fisso di iterazioni) per gestirlo. Inoltre (e questa è la vera salsa segreta imo!) I miei materiali sono riflettenti o rifrangenti, ma mai entrambi, il che rende i raggi così non si dividono quando rimbalzano. Il risultato finale di tutto ciò è il rendering raytracing di tipo ricorsivo, ma tramite iterazione a dimensione fissa, non ricorsione.
Alan Wolfe,

Ti piace la ricorsione della coda?
Tanmay Patil,

Non è necessario uno stack per eseguire la ricorsione della coda, poiché le funzioni ricorsive della coda possono essere convertite in funzioni iterative. Il compilatore OpenCL non lo fa automaticamente?
Anderson Green,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.