Rendimiento de bucle en un sombreador

11

Me pregunto cuál es la mejor manera de integrar una función de bucle dinámico en un sombreador.

Primero, parece que las matrices dinámicas no son posibles. Entonces, ¿es mejor crear una matriz de tamaño máximo y solo llenar una parte de ella o definir matrices con tamaños predefinidos?

Entonces, ¿cuál es la mejor manera de iterar sobre esta matriz?

¿Es mejor usar un bucle desenrollado o un bucle dinámico para algo entre 4 y 128 iteraciones? También he visto que es posible desenrollarlo a un número máximo predefinido de iteraciones y luego detenerlo con una condición como if (i == myCurrentMaximumIterationNumber).

Estera
fuente
2
¿Qué intentas hacer con la matriz y el bucle? Lo pregunto porque esto de alguna manera me suena como un problema XY . Dado que la mejor manera de usar condiciones y bucles en la GPU es abstenerse de usarlos, tal vez hay formas aún mejores en lugar de usar matrices y bucles en su caso.
Nero
Estoy implementando un efecto de dispersión del subsuelo del espacio de pantalla que actualmente funciona. Pero tengo algunas dudas sobre la forma en que uso el kernel de acuerdo con las actuaciones. Elegí hacer un tamaño máximo de matriz y llenar solo una parte y usar un bucle dinámico con un número dinámico de iteración que está relacionado con el contenido de matriz utilizado actualmente. Creo que hay cosas que hacer o saber al programar sombreadores de acuerdo con las actuaciones, por ejemplo. Y en mi opinión, los bucles son un tema de rendimiento común que podría seguir algunas reglas y tal vez "buenas prácticas", pero no encontré ninguna buena respuesta al respecto.
MaT

Respuestas:

6

Los compiladores de sombreado son extremadamente agresivos con respecto al desenrollado ya que los primeros HW a menudo no tenían control de flujo y el costo en los HW más recientes puede variar. Si tiene un punto de referencia con el que está probando activamente y una gama de hardware relevante, intente cosas para ver qué sucede. Su bucle dinámico es más susceptible a la intervención del desarrollador que un bucle estático, pero dejarlo al compilador sigue siendo un buen consejo a menos que tenga un punto de referencia disponible. Con un punto de referencia, la exploración vale la pena (y es divertida).

Por cierto, la mayor pérdida con un bucle dinámico en una GPU es que los "hilos" individuales en un frente de onda / deformación terminarán en diferentes momentos. Los subprocesos que se detienen más tarde obligan a todos los que terminan antes a ejecutar NOP.

Los bucles anidados deberían pensarse cuidadosamente: implementé un decodificador de entropía basado en bloques que codificaba corridas de ceros (para compresión similar a JPEG). La implementación natural era decodificar las corridas en un circuito interno cerrado, lo que significaba que a menudo solo un hilo estaba progresando; Al aplanar el bucle y probar explícitamente en cada subproceso si estaba decodificando una ejecución o no, mantuve todos los subprocesos activos a través del bucle de longitud fija (los bloques decodificados eran todos del mismo tamaño). Si los subprocesos fueran como subprocesos de la CPU, el cambio hubiera sido terrible, pero en la GPU en la que estaba funcionando, obtuve un aumento de 6 veces en el rendimiento (que aún era terrible, no había suficientes bloques para mantener ocupada la GPU) pero fue una prueba de concepto).

Daniel M Gessel
fuente