Es popular para mostrar contenido procesal dentro de la GPU, por ejemplo, en el demoscene (dibujando un único quad para llenar la pantalla y dejando que la GPU calcule los píxeles).
La marcha de rayos es popular:
Esto significa que la GPU está ejecutando un número desconocido de iteraciones de bucle por píxel (aunque puede tener un límite superior como maxIterations
).
¿Cómo afecta tener un bucle de longitud variable el rendimiento del sombreador?
Imagine el simple psuedocódigo de marcha de rayos:
t = 0.f;
while(t < maxDist) {
p = rayStart + rayDir * t;
d = DistanceFunc(p);
t += d;
if(d < epsilon) {
... emit p
return;
}
}
¿Cómo se ven afectadas las diversas familias de GPU convencionales (Nvidia, ATI, PowerVR, Mali, Intel, etc.)? ¿Sombreadores de vértices, pero particularmente sombreadores de fragmentos?
¿Cómo se puede optimizar?
opengl
glsl
opengl-es2
raytracing
Será
fuente
fuente
Respuestas:
Hubo una buena charla en GDC 2012 sobre la marcha de rayos de campo de distancia de GPU (y otros temas): http://directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/
En lo que respecta al rendimiento, las últimas tarjetas gráficas (clase DX11) ejecutan sombreadores en unidades SIMD que ejecutan 32 (NVIDIA) o 64 (AMD) "hilos" en forma sincronizada. Estos grupos son conocidos como deformaciones o frentes de onda. Para los sombreadores de píxeles, cada subproceso equivale a un píxel, por lo que esperaría que la unidad SIMD esté procesando algo así como un bloque de píxeles 8x4 (NVIDIA) o 8x8 (AMD) juntos. La ramificación y el control de flujo se realizan por frente de onda, por lo que todos los subprocesos en un frente de onda tienen que repetirse tantas veces como el píxel individual más profundo dentro de ese frente de onda. Las máscaras de carril SIMD desactivarán la ejecución de los píxeles que ya han terminado, pero aún tienen que seguir silenciosamente el control de flujo general del frente de onda. Esto significa, por supuesto, que el sistema es mucho más eficiente cuando la ramificación es coherente,
En mi experiencia, la sobrecarga de la rama sigue siendo bastante alta, incluso si todos los hilos en la rama de frente de onda son iguales. He visto ganancias de rendimiento en algunos casos al desenrollar el ciclo para amortizar algunos de los gastos generales de la sucursal. Sin embargo, depende de cuánto trabajo esté haciendo en cada iteración de bucle, por supuesto. Si el cuerpo del bucle tiene suficientes "cosas", desenrollar no será una victoria.
fuente
Sugiero leer Running Code en un Teraflop: Cómo funcionan los núcleos de sombreador GPU (pdf) de SIGGRAPH 2008: más allá del sombreado programable . Habla de ramificación dinámica.
fuente
Con respecto a la ramificación dinámica, una nota adicional (puede ser obvia, pero aún vale la pena señalarla para algunas personas): puede afectar gravemente el rendimiento de los bucles desenrollados (obviamente no puede desenrollar un bucle si hay un número no constante de iteraciones) .
fuente
int s = 0;
ahora para (int k = 1; k <= n; k ++) {s + = k;} es lo mismo que s = n * (n + 1) / 2
así que eso no es cierto en general: D
fuente