Flotador, doble o ambos para la clase de vectores 2D?

11

Actualmente estoy escribiendo un pequeño motor de juegos 2D multiplataforma basado en OpenGL para nuestro estudio. Cuando investigué qué clase de Vector 2D usar, me topé con tres paradigmas de diseño diferentes:

  • Flotador y llamada por valor, como en este artículo de Gamasutra . Parece ser rápido pero ofrece poca precisión (ver también este hilo ). Pro: rápido, portátil y compatible con la mayoría de las bibliotecas.

  • Doble y llamada por referencia. Si entiendo bien el artículo anterior, también podría usar 2 variables de doble precisión en lugar de los 4 números flotantes. De acuerdo con el hilo anterior, el doble aún es más lento que el flotador.

  • Plantilla para doble y flotante: El popular libro " Game Engine Architecture " utiliza plantillas para hacer posible usar flotante y doble según sea necesario. La desventaja obvia es la hinchazón de código. Además, dudo que el código pueda optimizarse sin básicamente escribir dos clases, de todos modos.

Apreciaría saber qué soluciones está utilizando en sus motores internos y cuán precisos son, por ejemplo, los motores de juegos populares, para poder decidir qué solución implementaré en nuestro motor. En este momento estoy pensando simplemente en usar la precisión de flotación y vivir con ella.

martinpi
fuente
¿Más lento dónde ? No se puede hablar de velocidad si eso no está vinculado a una arquitectura en particular.
o0 '.
2
@ Lo'oris: No conozco ninguna arquitectura donde el doble sea más rápido que el flotador.
En lugar de escribir su propia clase de vectores, considere usar Sony ( bulletphysics.org/Bullet/phpBB3/… ). Es una "biblioteca" de encabezado fácil de colocar que ya ha sido micro-optimizada, y todas las bibliotecas de vectores son básicamente la misma interfaz externa de todos modos.
@ Joe: ¿2 dobles en lugar de 4 flotadores?
o0 '.
@ Lo'oris: La pregunta está un poco extraña, no sé si el interlocutor está confundido o solo usted: utiliza dos dobles "en lugar de" cuatro flotantes cuando se trata de SIMD, porque el registro tiene 128 bits de ancho. Todavía necesita procesar un número igual de números, y lo está haciendo a media velocidad.

Respuestas:

9

Siempre uso float a menos que tenga una razón para usar double, tanto como uso int a menos que tenga una razón para usar int64_t.

Los flotadores no tienen problemas para hacer aritmética de enteros precisos hasta 2 24 , que es a lo que la mayoría de las personas temen (principalmente irracionalmente). Los dobles no resuelven el problema de que los valores comunes no sean representables exactamente; ya sea que obtenga 0.10000001 o 0.10000000000000001, aún debe asegurarse de que su código lo considere "igual" a 0.09999999.

Los dobles son más lentos en cada plataforma en la que te interesará escribir juegos, tomar el doble del ancho de banda de la memoria y tener menos instrucciones de CPU especializadas disponibles.

Los flotadores de precisión simple siguen siendo el estándar para las interfaces gráficas de hardware, tanto en el lado C / C ++ como en los sombreadores internos.

Probablemente necesitará un vector doble en algún momento, pero debe usarse cuando sea necesario, no de manera predeterminada.

En cuanto a la plantilla: tiene razón, para obtener el máximo rendimiento, de todas formas querrá especializar las plantillas manualmente. Aparte de eso, ejecuté algunas pruebas para un código con plantilla durante el fin de semana (haciendo un IntRect y FloatRect de 4 ple), y descubrí que la versión con plantilla tardó aproximadamente 20 veces más en compilarse que simplemente repetir el código, que ascendió a unas 15 líneas . La repetición apesta, pero esperar compilaciones apesta más, y no es como si fuera a necesitar un StringRect o FooRect.


fuente
"Los dobles son más lentos en cada plataforma [...] " - Cita necesaria.
cenit
3

El marco del juego Microsoft XNA tiene una clase Vector2 que utiliza flotantes. Esta sería mi mayor razón personal para ir con carrozas, ya que confío en que la sabiduría y la experiencia del equipo de XNA sean mucho mayores que las mías.

Me pareció bastante interesante leer la respuesta en esta pregunta de Stack Overflow: "Float vs Double Performance" . También hay un hilo de gamedev.net con una discusión sobre el doble rendimiento en las GPU. Creo que es seguro asumir que los dobles son más lentos que los flotantes, al menos en muchas GPU, y yo personalmente siempre utilicé las funciones flotantes de OpenGL sobre sus contrapartes dobles. Es posible que esto no se aplique hoy en día, pero si considera que no todos los que ejecutan su juego tienen la última GPU con soporte doble nativo, creo que esta es razón suficiente para usar flotadores y obtener ese rendimiento adicional.

Ricket
fuente
1
De la pregunta SO: "En los procesadores x86, al menos, flotante y doble se convertirán en un real de 10 bytes por la FPU para su procesamiento". Si bien esto es cierto, descuida las instrucciones SIMD y los requisitos de memoria adicional (= peor coherencia de caché, más ancho de banda de memoria) de los dobles, los cuales continúan haciéndolo más lento que flotante en las pruebas del mundo real.
Me imaginé que había una trampa. Deberías comentar eso en la respuesta SO, lo votaría.
Ricket
Ya está ahí como comentario.
1
Desde que mencionó XNA, también puedo señalar que Direct2D también utiliza flotadores de precisión simple.
Mike Strobel
Y para completar, OpenGL tiene versiones flotantes y dobles de sus métodos, por lo que es neutral en este sentido.
Ricket