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)
.
Respuestas:
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).
fuente