2012-04-14 8 views
17

Estoy interesado en información sobre la velocidad de sin() y cos() en Open GL Shader Language.Velocidad de las funciones cos() y sin() en sombreadores GLSL?

El GLSL Specification Document indica que:

Las funciones integradas básicamente se dividen en tres categorías:

  • ...
  • ...
  • representan un hardware de gráficos de operación es probable que acelere en algún momento. Las funciones de trigonometría se incluyen en esta categoría .

EDIT:

Como se ha señalado, contar ciclos de reloj de las operaciones individuales como sin() y cos() en realidad no cuentan toda la historia rendimiento.

Para aclarar mi pregunta, lo que realmente me interesa es si vale la pena optimizar sin() y cos() llamadas para casos comunes.

Por ejemplo, en mi aplicación, será muy común que el argumento sea 0. Lo mismo ocurre algo como esto sentido:

float sina, cosa; 

if (rotation == 0) 
{ 
    sina = 0; 
    cosa = 1; 
} 
else 
{ 
    sina = sin(rotation); 
    cosa = cos(rotation); 
} 

O el GLSL compilador o las sin() y cos() implementaciones cuidar de optimizaciones así para mí?

+1

¿Qué quiere decir con "GPU modernas que proporcionan aceleración de hardware para' sin() 'y' cos() '?" Si se ejecuta en la GPU, se puede decir que es hardware acelerado. En cualquier caso, lo mejor es probarlo y perfilarlo, ya que los ciclos de reloj en una GPU son algo sin sentido sin más contexto en cuanto a lo que estás haciendo. Incluso entre diferentes tarjetas del mismo proveedor, puede haber diferencias en el número de unidades de ejecución, por lo que los ciclos solo le dicen parte de la historia. – user1118321

+0

Con esas GPU, creo que tendrá el tiempo de ejecución más rápido posible de esas funciones trigonométricas. Interesante pregunta ... –

+0

Como se señala en [este] (http://stackoverflow.com/questions/10111898/glsl-relative-to-each-other-how-expensive-are-operations-like-multiply-divide) y [este] (http://stackoverflow.com/questions/8415251/performance-of-different-cg-glsl-hlsl-functions) pregunta, esta pregunta es esencialmente incontestable. Un uso particular de 'sin' puede costar * nada *, dependiendo de dónde lo use y el hardware. –

Respuesta

16

Por ejemplo, en mi aplicación que va a ser muy común que el argumento sea 0. Por lo tanto hace algo como esto sentido:

su compilador hará una de dos cosas

  1. Emitirá una rama condicional real. En el mejor de los casos posibles, si 0 es un valor que es coherente a nivel local (de modo que los grupos de sombreadores a menudo lleguen a 0 o que no sean cero juntos), entonces podría obtener un mejor rendimiento.
  2. Evaluará ambos lados de la condición, y solo almacene el resultado para el correcto de ellos. En ese caso, no has ganado nada.

En general, no es una buena idea usar la lógica condicional para bailar con un rendimiento tan pequeño como este. Tiene que ser realmente grande para que valga la pena, como un discard o algo así.

Además, tenga en cuenta que no es probable que la equivalencia de coma flotante funcione. No, a menos que realmente pase un atributo uniforme o de vértice que contenga exactamente 0.0 para el sombreador. Incluso la interpolación entre 0 y distinto de cero probablemente nunca producirá exactamente 0 para ningún fragmento.

+1

De hecho, estaría pasando el valor de 0.0 al sombreador como un vértice atributo. Pero un buen punto, si no estuviera probando que el valor es un pequeño epsilon lejos de 0, probablemente sería necesario. Pero, en primer lugar, parece que no valga la pena. – ulmangt

+0

Dependiendo de la cantidad de trabajo que cada sombreador tiene que hacer, puede ganar teniendo dos variantes, una para saber que es cero y otra donde no lo es. Pero cambiar el sombreado no es barato, por lo que depende de la carga de trabajo. – Robinson

+1

@NicolBolas Y en realidad, después de leer tu respuesta y recordar algo de mi CUDA, creo que hay una tercera opción: el sombreador puede evaluar el primer lado de la condición para los hilos donde 'rotation == 0' mientras los otros bloquean (o noop), luego evalúa el segundo lado mientras que el primer bloque. Lo cual obviamente sería malo también. Aunque eso supone que los sombreadores se evalúan de manera similar a los kernels CUDA. – ulmangt

2

No estoy seguro de si esto responde a su pregunta, pero es muy difícil decirle cuántos relojes/ranuras toma una instrucción, ya que depende mucho de la GPU. Por lo general, es un solo ciclo. Pero incluso si no, el compilador puede reorganizar el orden de ejecución de la instrucción para ocultar el costo real. Ciertamente, es más lento usar búsquedas de textura para sin/cos que para ejecutar las instrucciones.

+0

No veo ninguna mención de sincos() en la especificación http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.40.05.pdf ¿cuál es el nombre real de la función? ¿Es eso una extensión? – ulmangt

+0

Mis disculpas, en realidad creo que podría ser D3D solamente, y aun así creo que el compilador genera implícitamente una instrucción sin y una cos para ella. – Robinson

+0

FWIW, hay una instrucción Fragmento ARB 'SCS ' que devuelve seno (entrada.x) en el componente xy cos (entrada.x) en el componente y. – user1118321

5

Tendría que probar esto usted mismo, pero estoy bastante seguro de que la bifurcación en un sombreador es mucho más costosa que un cálculo sin o cos. Los compiladores GLSL son bastante buenos para optimizar los sombreadores, preocupándose por una optimización prematura. Si más tarde descubre que, a través de todo su programa, sus sombreadores son el cuello de botella, entonces puede preocuparse por optimizar esto.

Si desea ver un código de ensamblado de su sombreador para una plataforma específica, le recomiendo AMD GPU ShaderAnalyzer.

+0

"a ** un ** código de ensamblado". No hay "** el ** ensamblaje" para sombreadores. Cambia de una plataforma a otra. E incluso desde la revisión del controlador hasta la revisión del controlador. –

+0

Gracias, lo arreglaron. –

+0

Es probable que una rama con un uniforme bool sea gratuita. Utilicé esa técnica en este tipo de situaciones cuando era apropiado. –

6

Esta es una buena pregunta. Yo también me preguntaba esto.

Google'd links dicen cos y sin son de un solo ciclo en las tarjetas convencionales desde 2005 más o menos.

1

ver cuántos pecados se pueden obtener en un sombreado en una fila, en comparación con math.abs, frac, ect ... creo que un gtx 470 puede manejar 200 funciones de pecado por fragmento sin problemas, el marco será de 10 por ciento más lento que un sombreador vacío. es muy rápido, puede enviar resultados. Será un buen indicador de eficiencia computacional.

-2

El compilador evalúa ambas ramas, lo que hace que las condiciones sean bastante caras. Si usa tanto sen como cos en su sombreador, puede calcular solamente sin (a) y cos (a) = sqrt (1.0 - sin (a)) desde sin (x) * sin (x) + cos (x) * cos (x) siempre es 1.0

+1

sin (x) + cos (x) no es generalmente 1.0. Probablemente estés pensando en la identidad de que sin (x) * sin (x) + cos (x) * cos (x) es 1.0. Si bien esa identidad se puede usar para calcular un valor del otro, esto implica una raíz cuadrada, que probablemente sea tan costosa como calcular el valor. Entonces no es realmente útil. Además, las GPU modernas no suelen evaluar ambas ramas siempre que los valores de condición sean los mismos para todos los valores de fragmentos que se procesen juntos. –

+0

Sí, estaba pensando en cos^2 (x) + sin^2 (x) = 1 del teorema de Pitágoras. Mi error. –

Cuestiones relacionadas