2012-05-25 7 views
9

Me he encontrado con varias situaciones en las que se afirma que hacer un producto escalar en GLSL terminará ejecutándose en un ciclo. Por ejemplo:GLSL: ¿un producto de punto realmente solo cuesta un ciclo?

Vertex y procesadores de fragmentos operan en cuatro vectores, la realización de las instrucciones de cuatro componentes, tales como adiciones, multiplicaciones, multiplicar-acumula, o productos de punto en un solo ciclo.

http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter35.html

También he visto una reclamación en los comentarios en alguna parte que:

dot(value, vec4(.25)) 

habría una manera más eficiente de los valores promedio de cuatro, en comparación con:

(x + y + z + w)/4.0 

Una vez más, la afirmación era que el punto (vec4, vec4) se ejecutaría en un ciclo.

Veo que ARB says that dot product (DP3 and DP4) and cross product (XPD son instrucciones individuales, pero ¿eso significa que son tan costosas desde el punto de vista computacional como agregar un vec4? ¿Hay básicamente alguna implementación de hardware, en la línea de multiplicar-acumular en esteroides, en juego aquí? Puedo ver cómo algo así es útil en gráficos de computadora, pero hacer en un ciclo lo que podrían ser bastantes instrucciones por sí solos suena como mucho.

Respuesta

11

La pregunta no puede responderse de ninguna manera definitiva como un todo. El tiempo que tarda una operación en hardware no es solo específico del hardware, sino también , código específico. Es decir, el código circundante puede enmascarar por completo el rendimiento que requiere una operación, o puede hacerlo demorar más tiempo.

En general, no debe suponer que un producto escalar es de ciclo único.

Sin embargo, hay ciertos aspectos que sin duda puede ser respondida:

También he visto una reclamación en los comentarios en alguna parte que:

habría una manera más eficiente de los valores promedio de cuatro, en comparación a:

que sería de esperar que esto sea un poco cierto, siempre y cuando x, y, z, y w están en valores de coma flotante de datos diferentes en lugar de miembros de la misma vec4 (es decir, no son value.x, value.y, etc.). Si son elementos del mismo vector, diría que cualquier compilador de optimización decente debería compilar ambos con el mismo conjunto de instrucciones. Un buen peephole optimizer debería atrapar patrones como este.

Digo que es "un poco cierto", porque depende del hardware. La versión del producto punto no debe ser más lenta. Y nuevamente, si son elementos del mismo vector, el optimizador debería manejarlo.

instrucciones individuales, pero ¿eso significa que son tan costosas desde el punto de vista informático como hacer un vec4 add?

Usted no debe asumir que el montaje ARB tiene ningún relación con el código real instrucción de máquina hardware.

¿Hay básicamente alguna implementación de hardware, en la línea de multiplicar-acumular en esteroides, en juego aquí?

Si quiere hablar de hardware, es muy específico del hardware. Había una vez un hardware especializado de productos dot. Esto fue en los días del llamado "bumpmapping DOT3" y la era de Shaders DX8 temprana.

Sin embargo, para acelerar las operaciones generales, tuvieron que sacar ese tipo de cosas. Así que ahora, para la mayoría del hardware moderno (también conocido como: cualquier clase de Radeon HD o NVIDIA 8xxx o superior) denominado hardware DX10 u 11), los productos de punto hacen más o menos lo que dicen que hacen. Cada multiplicación/adición toma un ciclo.

Sin embargo, este hardware también permite un montón de paralelismo, por lo que podría tener 4 productos de puntos vec4 separados que ocurran simultáneamente. Cada uno tomaría 4 ciclos. Pero, siempre que los resultados de estas operaciones no se usen en los otros, todos pueden ejecutarse en paralelo. Y por lo tanto, los cuatro de ellos total tomarían 4 ciclos.

Así que de nuevo, es muy complicado. Y depende del hardware.

Su mejor apuesta es comenzar con algo que es razonable. Luego aprende sobre el hardware al que intentas codificar y trabaja desde allí.

+0

Ok, gracias. "No debe suponer que el ensamblado ARB tiene alguna relación con el código de instrucción de máquina de hardware real". es básicamente la respuesta concisa que estaba esperando. Parece que ARB es un nicho y es difícil encontrar un montón de material apto para Google. Esta fue una de esas cosas del tipo de "conocimiento tribal" que no pude verificar, y el hecho de que era cierto por un período de tiempo tiene sentido. Cosas interesantes. – ultramiraculous

0

la clave es que un vec4 puede ser 'operado' en una sola instrucción (vea el trabajo que Intel hizo en 16 operaciones de registro de bytes, también conocido como la base para el marco acelerado de IOS).

si empiezas a dividir y separar el vector ya no habrá una 'dirección de memoria única' del vector para realizar la operación.

4

Nicol Bolas manejó la respuesta práctica, desde la perspectiva del "ensamblaje ARB" o mirando los volcados IR. Voy a abordar la pregunta "¿Cómo pueden 4 múltiplos y 3 agrega ser un ciclo en el hardware ?! Eso suena imposible"..

Con la canalización pesada, cualquier instrucción se puede hacer para tener un rendimiento de un ciclo, sin importar cuán complejo sea.

¡No confunda esto con un ciclo de latencia!

Con una ejecución totalmente segmentada, se puede distribuir una instrucción en varias etapas de la canalización. Todas las etapas de la tubería operan simultáneamente.

Cada ciclo, la primera etapa acepta una nueva instrucción, y sus salidas pasan a la etapa siguiente. Cada ciclo, un resultado sale al final de la tubería.

Examinemos un producto de 4d puntos, para un núcleo hipotético, con una latencia múltiple de 3 ciclos y una latencia agregada de 5 ciclos.

Si esta tubería fuera diseñada de la peor manera, sin paralelismo vectorial, sería 4 multiplicaciones y 3 agregaciones, dando un total de 12 + 15 ciclos para una latencia total de 27 ciclos.

¿Esto significa que un producto escalar tarda 27 ciclos? Absolutamente no, porque puede comenzar uno nuevo en cada ciclo y recibe la respuesta 27 ciclos después.

Si tenía que hacer un producto de punto y tenía que esperar la respuesta, entonces tendría que esperar la latencia de 27 ciclos completa para obtener el resultado. Sin embargo, si tuvieras 1000 productos punto separados para calcular, tomaría 1027 ciclos. Los primeros 26 ciclos, no hubo resultados, en el ciclo 27 el primer resultado aparece al final, después de que se emitió la entrada número 1000, se necesitaron otros 26 ciclos para que los últimos resultados salgan al final. Esto hace que el producto escalar tome "un ciclo".

Los procesadores reales tienen el trabajo distribuido a través de las etapas de varias maneras, dando más o menos etapas de tubería, por lo que pueden tener números completamente diferentes a los que describo anteriormente, pero la idea sigue siendo la misma. En general, cuanto menos trabajo hagas por etapa, más corto podrá ser el ciclo del reloj.

+0

¡Esta es una respuesta redactada de manera descriptiva y la aprecio plenamente como tal! –

Cuestiones relacionadas