Son populaire pour rendre le contenu procédural à l'intérieur du GPU par exemple dans la demoscene (dessiner un seul quadruple pour remplir l'écran et laisser le GPU calculer les pixels).
La marche des rayons est populaire:
Cela signifie que le GPU exécute un nombre inconnu d'itérations de boucle par pixel (bien que vous puissiez avoir une limite supérieure comme maxIterations
).
Comment le fait d'avoir une boucle de longueur variable affecte-t-il les performances du shader?
Imaginez le simple pseudo-code de défilement des rayons:
t = 0.f;
while(t < maxDist) {
p = rayStart + rayDir * t;
d = DistanceFunc(p);
t += d;
if(d < epsilon) {
... emit p
return;
}
}
Comment les différentes familles de GPU (Nvidia, ATI, PowerVR, Mali, Intel, etc.) sont-elles affectées? Vertex shaders, mais particulièrement fragment shaders?
Comment peut-il être optimisé?
opengl
glsl
opengl-es2
raytracing
Volonté
la source
la source
Réponses:
Il y a eu une belle discussion au GDC 2012 sur la marche des rayons du champ de distance du GPU (et d'autres sujets): http://directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/
En ce qui concerne les performances, les dernières cartes graphiques (de classe DX11) exécutent des shaders sur les unités SIMD qui exécutent 32 (NVIDIA) ou 64 (AMD) "threads" en même temps. Ces groupes sont connus sous le nom de chaînes ou de fronts d'onde. Pour les pixel shaders, chaque thread équivaut à un pixel, donc je m'attends à ce que l'unité SIMD traite quelque chose comme un bloc de pixels 8x4 (NVIDIA) ou 8x8 (AMD) ensemble. Le branchement et le contrôle de flux sont effectués par front d'onde, de sorte que tous les threads d'un front d'onde doivent boucler autant de fois que le pixel individuel le plus profond de ce front d'onde. Les masques de voie SIMD désactiveront l'exécution pour les pixels qui sont déjà terminés, mais ils doivent toujours suivre silencieusement le contrôle de flux global du front d'onde. Cela signifie, bien sûr, que le système est beaucoup plus efficace lorsque la ramification est cohérente,
D'après mon expérience, les frais généraux de branche sont toujours assez élevés même si tous les threads de la branche de front d'onde sont identiques. J'ai vu des gains de performances dans certains cas en déroulant la boucle pour amortir une partie des frais généraux de la branche. Cependant, cela dépend de la quantité de travail que vous faites dans chaque itération de boucle, bien sûr. Si le corps de la boucle contient suffisamment de "trucs", le déroulement ne sera pas une victoire.
la source
Je suggère de lire Running Code at a Teraflop: How GPU Shader Cores Work (pdf) from SIGGRAPH 2008: Beyond Programmable Shading . Il parle de ramification dynamique.
la source
En ce qui concerne la ramification dynamique, une remarque supplémentaire (peut être évidente, mais mérite d'être notée pour certaines personnes): elle peut affecter gravement les performances des boucles non déroulées (vous ne pouvez évidemment pas dérouler une boucle s'il y a un nombre non constant d'itérations) .
la source
int s = 0;
maintenant pour (int k = 1; k <= n; k ++) {s + = k;} est le même que s = n * (n + 1) / 2
donc ce n'est pas vrai en général: D
la source