Impacto de los bucles de longitud variable en sombreadores GPU

9

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:

ingrese la descripción de la imagen aquí

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?

Será
fuente
Lamentablemente, esta pregunta es demasiado difícil de responder correctamente aquí. Aunque una respuesta ya dio puntos a una fuente que vale la pena leer (implica ramificación dinámica). +1 para el "tema" ..
teodron
1
@teodron no seas derrotista! Esperaba que alguien dijera que en las tarjetas de NVidia, los píxeles de la pantalla en bloques de 8x8 se iterarán tan profundamente como sea necesario, y que los bloques de 8x8 píxeles se pueden hacer en cualquier orden, o algo así; eso no es cierto, ese es el tipo de sabiduría que espero que la gente pueda compartir. Los enlaces en Larrabee, hmm, son bastante indirectos.
Será el
No parece que esté discutiendo sobre Larrabee, pero el chico de Stanford dio la misma charla dos años después, en 2010 ( puedes verlo aquí ). Según sus cifras, considerando un ciclo while, no entendí si los píxeles que "terminan" sus cálculos antes compensan cualquier rendimiento. En CUDA, los hilos esperan en una barrera. En analogía, ¿qué pasa con los hilos de sombreado?
teodron
@teodron, sí, he entendido CUDA y me he aplicado a las GPU; Estoy seguro de que están a la última, pero me gustaría que alguien con conocimientos interviniera; de todos modos, aquí hay algo relacionado williamedwardscoder.tumblr.com/post/26628848007/rod-marching
Será el

Respuestas:

8

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.

Nathan Reed
fuente
0

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) .

Gavan Woolery
fuente
-4

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

cañutillo
fuente
1
Es posible que te rechacen mucho porque nadie está muy seguro de lo que estás tratando de transmitir aquí o de lo que tiene que ver con la pregunta.
doppelgreener