Micro-optimización - BAD vs Game Development

12

En el desarrollo de juegos hay mucho C / C ++, en las aplicaciones empresariales C #. He visto que los desarrolladores de C / C ++ expresan preocupación sobre cómo una sola línea de código se traduce en ensamblaje. En .NET algunos entran en IL, raramente.

En C #, la "micro-optimización" está mal vista, es raro y generalmente es una pérdida de tiempo. Este no parece ser el caso en el desarrollo de juegos.

¿Qué crea específicamente esta inconsistencia? ¿Los juegos superan constantemente los límites del hardware? En caso afirmativo, a medida que el hardware mejora, ¿deberíamos esperar que los lenguajes de nivel superior se hagan cargo de la industria del juego?

No estoy buscando un debate sobre la viabilidad de C # como desarrollador de juegos. Sé que se ha hecho hasta cierto punto. Centrarse en la microoptimización. Específicamente, la diferencia entre Game Dev vs Aplicaciones dev.

ACTUALIZACIÓN
Por juego me refiero al desarrollo moderno a gran escala. Por ejemplo, MMORPG, Xbox, PS3, Wii ...

P.Brian.Mackey
fuente
3
He trabajado como desarrollador de juegos y desarrollador de aplicaciones y las diferencias son irrelevantes. La micro optimización sin perfilado está mal vista en ambos. Muchos juegos no tienen requisitos muy potentes y no requieren ninguna optimización. Algunas aplicaciones comerciales requieren requisitos mucho más estrictos (por ejemplo, tiempo de actividad y garantías en tiempo real) que un juego promedio de 60Hz.
Dave Hillier
1
Un factor adicional es que en las aplicaciones comerciales, generalmente puede elegir el hardware (dentro de lo razonable). Si necesito más potencia de procesamiento, puedo comprar otro servidor o pagar más tiempo con AWS. En los juegos, requerir el hardware más reciente convierte un juego de $ 60 en un juego y una tarjeta de video de $ 1,060. Si está desarrollando para consolas, la actualización del hardware puede significar retrasos durante años esperando la próxima generación. Cuando no puede obtener un mejor hardware, debe utilizarlo mejor.
Andrew
1
relacionado: wiki.c2.com/?PrematureOptimization
Peter

Respuestas:

17

En las aplicaciones empresariales, la CPU no siempre es el cuello de botella. Una aplicación comercial pasaría la mayor parte del tiempo esperando. P.ej:

  1. esperando los resultados de la consulta de la base de datos
  2. esperando que finalice la solicitud web
  3. esperando que el usuario realice una acción de IU

Es por eso que el código que optimiza el rendimiento del procesamiento no agrega demasiado valor.

La consideración principal es:

  1. Hora de comprar
  2. Simplicidad, ¿alguien más puede entender y mantener el código?
Shamit Verma
fuente
66
Señalaría que el código que optimiza las consultas de la base de datos puede mejorar en gran medida la usabilidad de las aplicaciones comerciales.
HLGEM
44
+1. La optimización de la base de datos y la red generalmente daría más por la inversión en aplicaciones comerciales. Por ejemplo, elección de JSON vs XML y ajuste de índices de base de datos
Shamit Verma
2
+1 pero deberías agregar el otro lado de la ecuación: el "bucle principal (s)" y el renderizado (s) en los juegos en los que se basa la fluidez del juego hacen que cada microsegundo pierda una pérdida de valor, porque la calidad es perceptible a la vista y otros sentidos.
Klaim
1
Bien dicho. Y, de hecho, después de haber desarrollado aplicaciones de negocios y desarrollo de juegos, pasé tiempo analizando una compleja consulta SQL tratando de obtener más rendimiento, al igual que pasé tiempo estudiando un bucle interno de un juego.
Carson63000
Todo vuelve a la optimización prematura es la raíz de todo mal . La creación de perfiles revela claramente que la mayor parte del tiempo empleado en una aplicación comercial promedio es IO de red + base de datos.
Alex Reinking
13

En aplicaciones comerciales, es muy raro que importen los microsegundos. En los juegos, es un hecho de la vida.

Si desea que un juego se ejecute a 60 cuadros por segundo, tiene ~ 16.67 milisegundos para hacer todo lo que se necesita hacer para ese cuadro: entrada, física, lógica de juego, audio, redes, IA, renderizado, etc. Si tiene suerte, correrá a 30 fps y tendrá 33.3 milisegundos de lujo. Si un marco lleva demasiado tiempo, sus comentarios se verán afectados, sus jugadores llenarán los foros de Internet con bilis y no venderá tanto como podría (sin mencionar el golpe a su orgullo profesional) y si realmente tiene mala suerte encontrará a su equipo codificando aplicaciones comerciales para ganarse la vida.

Por supuesto, los desarrolladores de juegos no se preocupan por cada línea, ya que, con experiencia y un perfilador decente, usted aprende qué líneas deben preocuparse. Por otro lado, esas preocupaciones a veces tocarán cosas que en el mundo empresarial probablemente se considerarían nanooptimizaciones en lugar de microoptimizaciones.

No espere que ningún lenguaje de alto nivel expulse a C ++ hasta que uno ofrezca un rendimiento comparable y predecible.

molbdnilo
fuente
8
En aplicaciones comerciales de alta frecuencia, ¡los microsegundos importan mucho!
quant_dev
2
@quant: Al igual que con la mayoría de las aplicaciones de procesamiento de flujo: robótica, redes eléctricas, cohetes, tecnología médica, etc. Acumule demasiado trabajo atrasado y puede ser demasiado tarde para cuando se ponga al día.
Aaronaught
@quant_dev: Las aplicaciones comerciales de alta frecuencia son muy raras.
molbdnilo
Ya no. Son más raros que las aplicaciones de contabilidad, pero más comunes que, por ejemplo, el software de diseño de aviones.
quant_dev
Los microsegundos también son importantes en las aplicaciones de negocios, el cuello de botella generalmente se encuentra en otros lugares (a través de la red, en una base de datos o sistema de archivos).
RubberDuck
9

Bien, entonces has visto desarrolladores de C y C ++ obsesionados con líneas individuales. Apuesto a que no se obsesionan con cada línea.

Hay casos en los que desea el máximo rendimiento, y esto incluye muchos juegos. Los juegos siempre han tratado de superar los límites de rendimiento para verse mejor que su competencia en el mismo hardware. Esto significa que aplica todas las técnicas habituales de optimización. Comience con algoritmos y estructuras de datos, y avance desde allí. Al usar un generador de perfiles, es posible encontrar dónde se está tomando la mayor parte del tiempo y dónde es posible obtener ganancias significativas de la micro-optimización de unas pocas líneas.

Esto no se debe a que los idiomas obligan a las personas a hacerlo, es que las personas eligen los idiomas en función de lo que quieren hacer. Si desea extraer el último rendimiento de un programa, no escribirá C # y compilará en el CLR y esperará que el compilador JIT (o lo que sea) haga un buen trabajo, escríbalo en algo donde pueda controlar en gran medida La salida. Utilizará C o C ++ (y probablemente un subconjunto restringido de C ++) y estudiará la salida en lenguaje ensamblador y los resultados del generador de perfiles.

Hay muchas personas que usan C y C ++ y no se preocupan demasiado por los detalles de la traducción, siempre que parezca lo suficientemente rápido.

David Thornley
fuente
7

¿Los juegos superan constantemente los límites del hardware?

Ellos si.

En caso afirmativo, a medida que el hardware mejora, ¿deberíamos esperar que los lenguajes de nivel superior se hagan cargo de la industria del juego?

En realidad no, porque a medida que el hardware mejora, los consumidores esperan que los juegos también mejoren. No esperan ver la misma calidad de juego desarrollada de manera más eficiente porque los desarrolladores usaron un lenguaje de nivel superior. Esperan que se les vuelen los calcetines con cada nueva plataforma.

Por supuesto, hay algo de movimiento. Cuando era un muchacho y me interesé por primera vez en el desarrollo de juegos, era un montaje escrito a mano, o largarme. Esta fue la era del Commodore 64. Hoy en día, por supuesto, C ++ es la lengua franca de la mayoría de los desarrollos de juegos. Y, de hecho, incluso hemos visto un movimiento hacia el uso de C ++ para el código del motor y un lenguaje de secuencias de comandos de nivel superior para el código lógico del juego. por ejemplo, LUA, o el motor Unreal tiene su propio lenguaje UnrealScript.

Carson63000
fuente
1
+1 una buena parte de los desarrolladores de juegos en estos días usan una capa de motor hiper optimizada escrita por otra persona, luego usan algo como Python, o C ++ menos meticuloso para envolver las cosas.
Morgan Herlocker
Es relevante notar que Unreal ahora ha movido sus secuencias de comandos "hacia atrás", de UnrealScript a C ++. Lo mejor de C ++ moderno es que le permite escribir código de baja latencia micro optimizado y una lógica concisa de alto nivel. La mayoría de los otros idiomas solo alcanzan un alto nivel al sacrificar la latencia y, a menudo, también el rendimiento.
Leftaroundabout
7

En C #, la "micro-optimización" está mal vista, es raro y generalmente es una pérdida de tiempo. Este no parece ser el caso en el desarrollo de juegos.

Si solo puede ensamblar su aplicación con código de alto nivel y código de biblioteca, seguro que es una pérdida de tiempo. Escríbalo en un idioma interpretado si lo desea en ese caso; No hará mucha diferencia. Si está tratando de implementar un motor de iluminación global de vanguardia que voxeliza el contenido dinámico de la escena sobre la marcha en tiempo real como lo hizo CryEngine 3 , naturalmente no puede librarse de la necesidad de micro-optimizar.


fuente
0

"Juego" es un término bastante amplio. Si tuviera, digamos, un MMORPG, las optimizaciones más pequeñas afectarían a muchos jugadores.

Los jugadores están, y probablemente siempre han estado, acostumbrados a una cantidad relativamente grande de cosas que suceden a la vez, en tiempo real. Seguro; en un momento, tener un Pacman o Tetris receptivo era el objetivo. Pero aún tenían que ser receptivos. Hoy en día, 3DMMORPGs a través de conexiones de red de caída de paquetes.

Seguro entiendo el deseo de optimizar.

Jonta
fuente
0

Los juegos realizan constantemente grandes cantidades de procesamiento en segundo plano. Las aplicaciones comerciales no lo hacen.

usuario16764
fuente
44
No hagas muchas aplicaciones de negocios, ¿verdad?
SOLO MI OPINIÓN correcta
2
Lo suficiente como para saber que las aplicaciones empresariales no necesitan actualizar su estado 60 veces por segundo. Además, dije específicamente "constantemente".
user16764
2
¿Has oído hablar del comercio en tiempo real?
SOLO MI OPINIÓN correcta
0

Siempre encontré el término "microoptimización", bastante ambiguo. Si algunos cambios en el nivel de instrucción en el diseño de la memoria y los patrones de acceso hacen algo 80 veces más rápido por parte de un profesional disciplinado que mide sus puntos críticos sin reducir la complejidad algorítmica, ¿es eso una "microoptimización"? Para mí eso es una "megaoptimización" para hacer algo 80 veces más rápido en un caso de uso del mundo real. Las personas tienden a hablar de estas cosas, como que tales optimizaciones tienen efectos microscópicos.

Ya no estoy trabajando en gamedev, pero trabajo en VFX en áreas como el trazado de ruta, y he visto muchas implementaciones de árboles BVH y KD que procesan ~ 0.5 millones de rayos por segundo en una escena compleja (y esto es con evaluación multiproceso). Hablando en términos generales, tiendo a ver una implementación directa de un BVH en un contexto de trazado de rayos a menos de 1 millón de rayos / seg incluso con una evaluación multiproceso. Excepto que Embree tiene un BVH que puede procesar más de 100 millones de rayos en la misma escena con el mismo hardware.

Esto se debe completamente a las "micro optimizaciones" de que Embree es 200 veces más rápido (el mismo algoritmo y estructura de datos), pero, por supuesto, la razón es mucho más rápido porque los desarrolladores de Intel son profesionales que se apoyan en sus perfiladores y medidas y Realmente sintonizado las áreas que importaban. No estaban cambiando el código de todos modos y cometiendo cambios que hicieron 0.000000001% de mejoras a costa de degradar significativamente la mantenibilidad. Estas fueron optimizaciones muy precisas aplicadas en manos juiciosas: podrían haber sido microscópicas en términos de enfoque pero macroscópicas en términos de efecto.

Naturalmente, con los requisitos de velocidad de fotogramas en tiempo real de los juegos, dependiendo de qué tan alto o bajo nivel estés trabajando con el motor del juego (incluso los juegos hechos con UE 4 a menudo se implementan al menos parcialmente en un script de alto nivel, pero no, digamos, las partes más críticas del motor de física), las micro optimizaciones se convierten en un requisito práctico en ciertas áreas.

Otra área muy básica que nos rodea a diario es el procesamiento de imágenes, como desenfocar imágenes de alta resolución en tiempo real y tal vez hacer otros efectos en ellas como parte de una transición que probablemente todos hemos visto en alguna parte, tal vez incluso un efecto de sistema operativo. No puede implementar necesariamente tales operaciones de imagen desde un bucle cero a través de todos los píxeles de una imagen y esperar tales resultados en tiempo real a velocidades de cuadro coincidentes. Si se trata de CPU, generalmente estamos viendo SIMD y algunos microajustes, o estamos viendo sombreadores de GPU que tienden a requerir una mentalidad de nivel micro para escribir de manera efectiva.

En caso afirmativo, a medida que el hardware mejora, ¿deberíamos esperar que los lenguajes de nivel superior se hagan cargo de la industria del juego?

Dudo que los avances de hardware por sí solos puedan hacer eso, porque a medida que avanza el hardware, también lo hacen las instrucciones y la tecnología (por ejemplo, física en la GPU), y las técnicas, y las expectativas de los clientes sobre lo que quieren ver y la competencia. formas que a menudo hacen que los desarrolladores vuelvan a ser de bajo nivel, como en el caso de los desarrolladores web que ahora escriben sombreadores GLSL de bajo nivel en WebGL (el desarrollo web de este tipo en particular podría decirse que es incluso más bajo que hace una década o dos, ya que GLSL es un lenguaje tipo C de nivel extremadamente bajo, y nunca habría adivinado hace una o dos décadas que algunos desarrolladores web aceptarían escribir sombreadores de GPU de bajo nivel).

Si va a haber una manera de que las áreas críticas para el rendimiento se muevan a lenguajes de nivel superior, tendrá que provenir más del software, los compiladores y las herramientas que tenemos disponibles tal como lo veo. El problema para mí en cualquier futuro previsible no es que el hardware no sea lo suficientemente potente. Tiene más que ver con la forma en que no podemos encontrar maneras de hablar con mayor eficacia cada vez que cambia y avanza sin volver a su propio idioma. En realidad, es el rápido ritmo al que cambia el hardware lo que hace que la programación de alto nivel sea bastante difícil de alcanzar para estas áreas, como lo veo, ya que si hipotéticamente nuestro hardware dejara de avanzar de la nada durante las siguientes décadas,

Curiosamente en estos días, cuando estoy trabajando en áreas genuinas de rendimiento crítico, tengo que pensar un poco más bajo que lo que comencé (a pesar de que comencé en la era Borland Turbo C DOS). Porque en aquel entonces el caché de la CPU era casi inexistente. En su mayoría, solo era DRAM y registros, lo que significaba que podía concentrarme más en la complejidad algorítmica y escribir estructuras vinculadas como árboles de una manera muy directa sin tener mucho impacto en el rendimiento. En estos días, los detalles de bajo nivel del caché de la CPU dominan mi pensamiento casi tanto como el algoritmo en sí. Y del mismo modo, tenemos máquinas multinúcleo que deben hacernos pensar en multihilo y atómicos y mutexes y seguridad de subprocesos y estructuras de datos concurrentes, etc., lo que yo diría es, en muchos aspectos, un enfoque de nivel mucho más bajo (como en, no tan humanamente intuitivo) que cuando comencé.

Curiosamente, eso me parece muy cierto ahora. Creo que hoy me impactan más las complejidades subyacentes y de bajo nivel y los detalles del hardware que hace 30 años, haciendo mi mejor esfuerzo para quitarme las gafas de nostalgia. Por supuesto, podríamos haber hablado un poco de ensamblaje aquí y tener que lidiar con algunos detalles sangrientos como XMS / EMS. Pero en su mayor parte, diría que había menos complejidad y conocimiento de hardware y compiladores que requería en aquel entonces de lo que necesito hoy cuando estoy trabajando en áreas críticas de rendimiento. Y eso casi parece cierto para toda la industria si dejamos de lado como escribirif/else declaraciones de una manera un poco más legible para los humanos y considere cuánto piensan las personas en general en estos días más sobre los detalles de nivel inferior del hardware (desde múltiples núcleos a GPU a SIMD a caché de CPU y los detalles internos de cómo sus compiladores / intérpretes / las bibliotecas funcionan y así sucesivamente).

Nivel alto! = Menos eficiente

Volviendo a esta pregunta:

En caso afirmativo, a medida que el hardware mejora, ¿deberíamos esperar que los lenguajes de nivel superior se hagan cargo de la industria del juego?

Para mí no se trata de hardware. Se trata de optimizadores y herramientas. Cuando comencé, la gente prácticamente escribía todos los juegos de consola en ensamblador, y había una verdadera ventaja de rendimiento, especialmente dada la falta de compiladores de calidad que generaban 6502.

A medida que los compiladores de optimización de C se volvieron más inteligentes en sus optimizaciones, comenzaron a llegar a un punto en el que el código de nivel superior escrito en C rivalizaba y ocasionalmente incluso superaba el código escrito por los mejores expertos en ensamblaje en muchas áreas (aunque no siempre), y eso hizo que fuera obvio adoptar C para al menos la mayor parte de la codificación de un juego. Y un cambio similar ocurrió gradualmente en algún momento con C ++. La adopción de C ++ fue más lenta ya que creo que el aumento de la productividad de pasar de ensamblado a C probablemente podría llegar a un acuerdo unánime de los gamedevs que escriben juegos no triviales por completo en ASM en lugar de pasar de C a C ++.

Pero estos cambios no se debieron a que el hardware se volviera más poderoso, sino que los optimizadores para estos lenguajes hicieron que el nivel más bajo (aunque no siempre del todo, hay algunos casos oscuros) obsoleto.

Si puede imaginar un escenario hipotético en el que podríamos escribir código en el código de más alto nivel imaginable, sin preocuparse por subprocesos múltiples o GPU o errores de caché o algo por el estilo (tal vez ni siquiera estructuras de datos específicas), y el optimizador era como inteligencia artificial inteligente y podría descubrir los diseños de memoria más eficientes reorganizando y compactando nuestros datos, descubra que podría usar alguna GPU aquí y allá, paralelizar algún código aquí y allá, usar algo de SIMD, tal vez perfilarse y seguir optimizando su IR como humanos respondiendo a los puntos críticos del generador de perfiles, y lo hizo de una manera que supera a los mejores expertos del mundo, entonces sería una obviedad incluso para aquellos que trabajan en los campos más críticos de rendimiento adoptarlo ... y eso es un avance proveniente de optimizadores ridículamente inteligentes, no de hardware más rápido.

Dragon Energy
fuente
0

En C #, la "micro-optimización" está mal vista, es raro y generalmente es una pérdida de tiempo. Este no parece ser el caso en el desarrollo de juegos.

Tienes un problema de terminología aquí. Estás usando las palabras correctamente, pero los desarrolladores de juegos y la gente de negocios están usando el mismo término de dos maneras muy diferentes.

Para las empresas, la "micro optimización" significa acelerar un paso muy pequeño en el proceso empresarial general implementado por el software. La razón por la que está mal visto es típicamente una de:

  1. Dinero extra gastado entregando el mismo valor comercial, a unos segundos más rápido. El dinero ahorrado en las mejoras de velocidad proviene de un conjunto diferente de dinero (el tiempo del usuario), por lo que el negocio generalmente no se beneficia del esfuerzo que gasta, el cliente lo hace a expensas del negocio.
  2. Por lo general, los programadores de negocios tienen mala visibilidad en el proceso comercial general, por lo que una optimización de un solo paso podría no generar buenos beneficios para el proceso general. Por ejemplo, si hace que el 3% del proceso sea 10 veces más rápido, ha acelerado todo el proceso un 2,7%.
  3. Por lo general, las empresas tienen una gran lista de trabajo restante que tiene cierto valor comercial, y priorizarían agregar ese valor en lugar de entregar el mismo valor en un (probablemente) menor tiempo.

El desarrollo del juego es una bestia diferente. La "micro optimización" está ahorrando una pequeña cantidad de tiempo en una función o rutina.

  1. Los sistemas de juego tienden a estar sujetos al ciclo de renderizado. Actualmente, el estándar de oro es de 60 cuadros por segundo, por lo que todo lo que se va a calcular debe hacerse y mostrarse en la pantalla en 1/60 de segundo.
  2. Esto significa que a menudo las mismas rutinas se llaman de miles a cientos de miles de veces en el transcurso de un juego. Por lo tanto, una mejora de 10 veces en una sola función se magnifica en valor por la cantidad de veces que se sentirán los beneficios de la mejora.
  3. El fracaso en lograr la tasa de renderizado tiene un impacto en la presentación del juego. El video se volverá entrecortado, los personajes se animarán con saltos y saltos en lugar de movimientos fluidos. Esto inmediatamente saca al jugador de la inmersión del juego y lo cuestiona el valor del juego.

Entonces, en los negocios, a nadie le importa si la forma de un proceso comercial de 4 pasos se presenta en 0.6 segundos o 0.5 segundos. En los juegos, a uno le importa si una rutina que dura 200 ms se puede reducir a la ejecución en 100 ms.

Se trata del valor entregado al cliente, las necesidades del cliente y la relación costo-beneficio del cambio.

Edwin Buck
fuente
-1

Tiene que ver con por qué esa herramienta fue seleccionada para un trabajo en particular.

Los golfistas se obsesionan con la dirección y la fuerza que aplican con un putter, no tanto cuando usan el controlador.

¿Por qué? Porque son diferentes tipos de disparos. Para conducir, desea obtenerlo en la calle con la máxima distancia. Para un putt, quieres meterlo exactamente en el hoyo.

Lo mismo se aplica aquí. Los desarrolladores de juegos eligen C ++ porque les da control sobre el rendimiento de diferentes operaciones. Si ha elegido eso, querrá aprovecharlo.

JohnMcG
fuente
-3

La mayoría de las aplicaciones comerciales se escriben como herramientas internas. Las expectativas sobre la usabilidad de estas herramientas son mucho más bajas que en el caso del software vendido a clientes masivos. Es bastante común que una aplicación comercial interna tenga menús y cuadros de diálogo que reaccionan lentamente a los clics del mouse, ventanas que se vuelven a dibujar con retraso o incluso una GUI escrita en Swing (¡el horror!). Esto se debe a una serie de razones (es más importante que el software sea personalizable que muy "ágil", los usuarios del software no tienen opción de usar o no el software en cuestión, las personas que hacen decisión de instalar el software no lo utilicen ellos mismos ...). La consecuencia de todo esto es que los desarrolladores de estas herramientas no pasan mucho tiempo optimizando la capacidad de respuesta de la aplicación, pero se preocupa mucho por la extensibilidad y la cantidad de características. Base de clientes diferente => objetivos de diseño diferentes => metodología diferente.

Tenga en cuenta que una aplicación empresarial dirigida a un público masivo, como Excel, está muy optimizada.

cuant_dev
fuente