¿Cuándo es un sombreador de cálculo más eficiente que un sombreador de píxeles para el filtrado de imágenes?
On febrero 1, 2021 by adminLas operaciones de filtrado de imágenes, como desenfoques, SSAO, bloom, etc., generalmente se realizan mediante sombreadores de píxeles y operaciones de «recopilación», donde cada invocación del sombreador de píxeles emite un número de búsquedas de texturas para acceder a los valores de píxeles vecinos y calcula el valor de un solo píxel del resultado. Este enfoque tiene una ineficacia teórica en el sentido de que se realizan muchas búsquedas redundantes: las invocaciones de sombreadores cercanos recuperarán muchos de los mismos texels.
Otra forma de hacerlo es con los sombreadores de cálculo. Estos tienen la ventaja potencial de poder compartir una pequeña cantidad de memoria en un grupo de invocaciones de sombreadores. Por ejemplo, puede hacer que cada invocación obtenga un texto y almacenarlo en la memoria compartida, luego calcular los resultados desde allí. Esto podría o no ser más rápido.
La pregunta es bajo qué circunstancias (si alguna vez) es el método compute-shader realmente más rápido que el método de sombreado de píxeles? ¿Depende del tamaño del kernel, ¿Qué tipo de operación de filtrado es, etc.? Claramente, la respuesta variará de un modelo de GPU a otro, pero estoy interesado en escuchar si hay alguna tendencia general.
Comentarios
- Creo que la respuesta es » siempre » si el sombreador de cálculo se realiza correctamente. Esto no es trivial para Un sombreador de cálculo también es una mejor combinación que un sombreador de píxeles conceptualmente para los algoritmos de procesamiento de imágenes. Sin embargo, un sombreador de píxeles proporciona menos margen para escribir filtros de bajo rendimiento.
- @bernie ¿Puede aclarar qué ‘ s necesarios para que el sombreador de cálculo » se haga correctamente «? ¿Quizás escribir una respuesta? Siempre es bueno tener más perspectivas sobre el tema. 🙂
- ¡Ahora mira lo que me hiciste hacer! 🙂
- Además de compartir el trabajo a través de subprocesos, la capacidad de usar computación asíncrona es una gran razón para usar sombreadores de cálculo.
Respuesta
Una ventaja arquitectónica de los sombreadores de cálculo para el procesamiento de imágenes es que se saltan el paso ROP . Es muy probable que las escrituras de los sombreadores de píxeles pasen por todo el hardware de mezcla habitual, incluso si no lo utiliza. En términos generales, los sombreadores informáticos pasan por una ruta diferente (y a menudo más directa) a la memoria, por lo que puede evitar un cuello de botella que de otro modo tendría. He oído hablar de ganancias de rendimiento bastante considerables atribuidas a esto.
Una desventaja arquitectónica de los sombreadores de cálculo es que la GPU ya no sabe qué elementos de trabajo se retiran a qué píxeles. Si están usando la canalización de sombreado de píxeles, la GPU tiene la oportunidad de empaquetar el trabajo en un frente de onda / deformación que escribe en un área del destino de procesamiento que es contigua en la memoria (que puede ser Orden Z en mosaico o algo así por razones de rendimiento). Si está utilizando una canalización de procesamiento, es posible que la GPU ya no funcione en lotes óptimos, lo que lleva a un mayor uso del ancho de banda.
Usted Sin embargo, puede convertir ese empaquetado de frente de onda / deformación alterado en una ventaja nuevamente, si sabe que su operación en particular tiene una subestructura que puede explotar al empaquetar el trabajo relacionado en el mismo grupo de hilos. Como dijo, en teoría podría Dar un descanso al hardware de muestreo muestreando un valor por carril y colocando el resultado en la memoria compartida en grupo para otros sus carriles para acceder sin muestreo. Que esto sea una ganancia depende de lo costosa que sea la memoria compartida en grupo: si es más barata que la caché de textura de nivel más bajo, entonces esto puede ser una ganancia, pero no hay garantía de eso. Las GPU ya manejan bastante bien las recuperaciones de texturas altamente locales (por necesidad).
Si tiene una etapa intermedia en la operación en la que desea compartir resultados, puede tener más sentido usar memoria compartida en grupo (ya que no puede recurrir al hardware de muestreo de texturas sin haber escrito su resultado intermedio en la memoria). Desafortunadamente, tampoco puede depender de tener resultados de cualquier otro grupo de subprocesos, por lo que la segunda etapa tendría que limitarse solo a lo que está disponible en el mismo azulejo. Creo que el ejemplo canónico aquí es calcular la luminancia promedio de la pantalla para la exposición automática. También podría imaginarme la combinación de muestreo superior de textura con alguna otra operación (ya que el muestreo superior, a diferencia del muestreo inferior y los desenfoques, no depende de ningún valor fuera de un mosaico determinado).
Comentarios
- Dudo seriamente que el ROP agregue una sobrecarga de rendimiento si la combinación está deshabilitada.
- @GroverManheim ¡Depende de la arquitectura! El paso de fusión de salida / ROP también tiene que lidiar con las garantías de pedido incluso si se combinan Con un triángulo de pantalla completa no hay ‘ ningún peligro real de pedido, pero es posible que el hardware no lo sepa.Puede haber rutas rápidas especiales en el hardware, pero sabiendo con certeza que califica para ellas…
Respuesta
John ya ha escrito una gran respuesta , así que considere esta respuesta como una extensión de la suya.
Actualmente estoy trabajando mucho con sombreadores de cálculo para diferentes algoritmos. En general, he descubierto que los sombreadores de cómputo pueden ser mucho más rápidos que su sombreador de píxeles equivalente o transformar alternativas basadas en comentarios.
Una vez que entiendes cómo funcionan los sombreadores de cómputo, también hacen un mucho más sentido en muchos casos. El uso de sombreadores de píxeles para filtrar una imagen requiere configurar un búfer de fotogramas, enviar vértices, usar múltiples etapas de sombreado, etc. ¿Por qué debería ser necesario para filtrar una imagen? Estar acostumbrado a renderizar quads de pantalla completa para el procesamiento de imágenes es sin duda la única razón «válida» para seguir usándolos en mi opinión. Estoy convencido de que un recién llegado al campo de los gráficos computarizados encontrará que los sombreadores computacionales se adaptan mucho más al procesamiento de imágenes que al renderizado en texturas.
Su pregunta se refiere al filtrado de imágenes en particular, así que no voy a dar más detalles demasiado sobre otros temas. En algunas de nuestras pruebas, simplemente configurar una retroalimentación de transformación o cambiar los objetos de framebuffer para renderizar a una textura podría incurrir en costos de rendimiento de alrededor de 0.2ms. ¡Tenga en cuenta que esto excluye cualquier renderizado! En un caso, mantuvimos exactamente el mismo algoritmo adaptado para computar sombreadores y vimos un aumento notable del rendimiento.
Cuando se utilizan compute shaders, se puede usar más silicio en la GPU para hacer el trabajo real. Todos estos pasos adicionales son necesarios cuando se usa la ruta del sombreador de píxeles:
- Ensamblaje de vértices (leer los atributos de vértice, divisores de vértice, conversión de tipo, expandirlos a vec4, etc.)
- El sombreador de vértices debe programarse sin importar cuán mínimo sea
- El rasterizador tiene que calcular una lista de píxeles para sombrear e interpolar las salidas de los vértices (probablemente solo las coordenadas de textura para el procesamiento de imágenes)
- Todos los diferentes estados (prueba de profundidad, prueba alfa, tijera, mezcla) deben configurarse y administrarse
Se podría argumentar que todas las ventajas de rendimiento mencionadas anteriormente podrían ser negadas por un conductor inteligente. Estarías en lo cierto. Dicho controlador podría identificar que está renderizando un quad de pantalla completa sin pruebas de profundidad, etc. y configurar una «ruta rápida» que omita todo el trabajo inútil realizado para admitir sombreadores de píxeles. No me sorprendería que algunos controladores lo hicieran esto para acelerar los pases de posprocesamiento en algunos juegos AAA para sus GPU específicas. Por supuesto, puede olvidarse de cualquier tratamiento de este tipo si no está trabajando en un juego AAA.
Sin embargo, lo que el controlador no puede hacer es encontrar mejores oportunidades de paralelismo ofrecidas por el proceso de sombreado de cálculo. Tome el ejemplo clásico de un filtro gaussiano. Con los sombreadores de cálculo, puede hacer algo como esto (separar el filtro o no):
- Para cada grupo de trabajo, divida el muestreo de la imagen de origen entre el tamaño del grupo de trabajo y almacene los resultados en memoria compartida de grupo.
- Calcule la salida del filtro utilizando los resultados de muestra almacenados en la memoria compartida.
- Escriba en la textura de salida
El paso 1 es la clave aquí. En la versión del sombreador de píxeles, la imagen de origen se muestrea varias veces por píxel. En la versión de compute shader, cada texto fuente se lee solo una vez dentro de un grupo de trabajo. Las lecturas de texturas usualmente usan una caché basada en mosaicos, pero esta caché sigue siendo mucho más lenta que la memoria compartida.
El filtro gaussiano es uno de los ejemplos más simples. Otros algoritmos de filtrado ofrecen otras oportunidades para compartir resultados intermedios dentro de grupos de trabajo utilizando memoria compartida.
Sin embargo, hay una trampa. Los sombreadores informáticos requieren barreras de memoria explícitas para sincronizar su salida. También hay menos salvaguardias para proteger contra accesos erróneos a la memoria. Para los programadores con buenos conocimientos de programación paralela, los sombreadores de cálculo ofrecen mucha más flexibilidad. Sin embargo, esta flexibilidad significa que también es más fácil tratar los sombreadores de cálculo como código C ++ ordinario y escribir código lento o incorrecto.
Referencias
- Página wiki OpenGL Compute Shaders
- DirectCompute: Optimizaciones y mejores prácticas, Eric Young, NVIDIA Corporation, 2010 [pdf]
- Programación eficiente de sombreadores de cómputo, Bill Bilodeau, AMD, 2011? [pps]
- DirectCompute para juegos: potencia tu motor con Compute Shaders, Layla Mah & Stephan Hodes, AMD, 2013, [pps]
- Optimizaciones de Compute Shader para GPU AMD: reducción paralela, Wolfgang Engel, 2014
Comentarios
- El paralelismo de muestreo mejorado que describe es intrigante: Tengo una simulación fluida que ya está implementada con sombreadores de cómputo con muchas instancias de múltiples muestras por píxel. Usar la memoria compartida en grupo para hacer un muestreo único con una barrera de memoria como usted describe parece genial, pero I ‘ m colgado en un bit – ¿cómo accedo a los píxeles vecinos cuando caerían en un grupo de trabajo diferente? Por ejemplo, si tengo un dominio de simulación de 64×64, distribuido en un despacho (2,2,1) de numthreads (16,16,1), ¿cómo obtendría el píxel con id.xy == [15,15] sus píxeles vecinos? ?
- En ese caso, veo 2 opciones principales. 1) aumente el tamaño del grupo por encima de 64 y solo escriba los resultados para los 64×64 píxeles. 2) primera muestra 64 + nX64 + n dividida de alguna manera en su grupo de trabajo de 64×64 y luego use esa cuadrícula » input » más grande para los cálculos . La mejor solución depende de sus condiciones específicas, por supuesto, y le sugiero que escriba otra pregunta para obtener más información, ya que los comentarios no son adecuados para esto.
Responder
Me encontré con este blog: Optimizaciones de Compute Shader para AMD
Dados los trucos que se pueden hacer hecho en compute shader (que son específicos solo para compute shaders) Tenía curiosidad por saber si la reducción paralela en compute shader era más rápida que en el sombreador de píxeles. Le envié un correo electrónico al autor, Wolf Engel, para preguntarle si había probado el sombreador de píxeles. Él respondió que sí, y cuando escribió la publicación del blog, la versión del sombreador de cómputo era sustancialmente más rápida que la versión del sombreador de píxeles. También agregó que hoy las diferencias son aún mayores. Por lo tanto, aparentemente hay casos en los que el uso del sombreador de cálculo puede ser una gran ventaja.
Deja una respuesta