2009-02-21 16 views
22

No sé cómo funcionan mucho los juegos comerciales, pero los juegos de código abierto con los que me he encontrado no parecen estar muy conectados. Lo mismo ocurre con la mayoría de las otras aplicaciones de escritorio, normalmente se utilizan dos o tres subprocesos (por ejemplo, lógica de programa y actualizaciones de GUI).¿Por qué los programas grandes (como los juegos) no usan muchos hilos diferentes?

¿Por qué los juegos no tienen muchos hilos? Por ejemplo, hilos separados para física, sonido, gráficos, inteligencia artificial, etc.

+2

Paralelismo es difícil. No solo "wow, esto es complicado", sino "teóricamente, muchos problemas no son paralelizables". –

Respuesta

14

Muchos juegos actualmente usan sistemas de "tareas" o "trabajos" para el procesamiento en paralelo. Es decir, el juego genera un número fijo de subprocesos de trabajo que se utilizan para tareas múltiples. El trabajo se divide en pequeños fragmentos y se pone en cola, luego se envía para ser procesado por los hilos de trabajo a medida que estén disponibles.

Esto se está volviendo especialmente común en las consolas. La PS3 se basa en la arquitectura de la celda, por lo que debe usar el procesamiento paralelo para obtener el mejor rendimiento del sistema. Xbox 360 puede emular una configuración de tareas/tareas diseñada para PS3 ya que tiene múltiples núcleos. Probablemente, para la mayoría de los juegos, la mayoría del diseño del sistema se compartirá entre las bases de código de 360, PS3 y PC, por lo que es muy probable que las PC utilicen el mismo tipo de táctica.

Si bien es difícil escribir código multi-hilo, ya que muchas de las otras respuestas indican, creo que hay algunas otras razones de las cosas que estamos viendo:

  • En primer lugar, muchos juegos de código abierto son algunos años. Especialmente con esta generación de consolas, la programación paralela se está volviendo popular e incluso necesaria como se mencionó anteriormente.
  • En segundo lugar, muy pocos proyectos de código abierto parecen estar preocupados por obtener el mayor rendimiento posible. Como John Carmack señaló al proyecto GLX de Utah, el código altamente optimizado a menudo es más difícil de mantener que el código no optimizado, por lo que este último generalmente sería el preferido en contextos de fuente abierta.
  • En tercer lugar, no tomaría una pequeña cantidad de hilos creados por un juego para significar que no está utilizando trabajos paralelos bien.
15

La razón principal es que, por más elegante que parezca, utilizar múltiples hilos en un programa tan complicado como un juego en 3D es realmente, realmente, muy difícil. Además, antes de la introducción relativamente reciente de los sistemas multi-core de bajo costo, el uso de múltiples hilos no ofrecía mucho de un incentivo de rendimiento.

23

No conozco los juegos que ha jugado, pero la mayoría de los juegos ejecutan el sonido en un hilo separado. Código de red, al menos los escuchas de socket se ejecutan en un hilo separado.

Sin embargo, el resto del motor del juego generalmente se ejecuta en un solo hilo. Hay razones para esto. Por ejemplo, la mayoría del procesamiento en un juego ejecuta una cadena única de dependencias. Los gráficos dependen del estado del motor de física al igual que la inteligencia artificial. Diseñar para múltiples hilos significa que debe tener latencia de cuadro entre los diversos subsistemas para concurrencia. Usted obtiene un tiempo de respuesta más rápido y un juego más ágil si estos subsistemas se calculan linealmente en cada cuadro. La parte del juego que más se beneficia de la paralelización es, por supuesto, el subsistema de renderización que se descarga en tarjetas aceleradoras de gráficos altamente paralelizadas.

0

Hay muchos problemas con las condiciones de carrera y el bloqueo de datos cuando se utilizan muchos subprocesos. Dado que las diferentes partes de los juegos son bastante dependientes entre sí, no tiene mucho sentido hacer toda la ingeniería adicional necesaria para usar un montón de hilos.

1

Estaba a punto de publicar lo mismo que William, pero me gustaría ampliarlo un poco. Es muy difícil escribir un código óptimo para el futuro. Dada la elección entre escribir algo que se escalará al hardware que no tienes o escribir algo que funcionará en el hardware que tienes, la mayoría de la gente elegirá hacer lo último. Dado que el paradigma de un solo núcleo ha estado con nosotros durante tanto tiempo, la mayoría de los códigos que se han escrito (especialmente para los juegos en los que existe una presión extrema para que salga la puerta) no son una prueba de futuro.

x86 ha sido muy amable con los programadores de juegos, ya que no hemos tenido que pensar en las ramificaciones de plataformas de hardware menos permisivas.

0

Es muy difícil utilizar subprocesos sin problemas, y la mayoría de las API de GUI se basan en la codificación controlada por eventos de todos modos. Los subprocesos requieren el uso de mecanismos de bloqueo que agreguen demora al código, y con frecuencia ese retraso es impredecible dependiendo de quién esté sosteniendo el candado en ese momento.

Me parece sensato tener un solo (o tal vez muy pocos) hilos que manejen las cosas de una forma controlada por eventos en lugar de cientos de hilos que causan errores extraños e irrepetibles.

1

Aparte de los desafíos técnicos de la programación para múltiples núcleos, los juegos comerciales tienen que funcionar bien en sistemas de gama baja sin núcleos múltiples para ganar dinero.

Ahora que los procesadores multi-núcleo han estado funcionando por un tiempo y las principales consolas de juegos tienen múltiples núcleos, es solo cuestión de tiempo antes de que dual core aparezca en la lista de requisitos mínimos del sistema para juegos de PC.

Aquí hay un enlace a an interview with Orion Granatir de Intel, donde habla de conseguir que los desarrolladores de juegos aprovechen el multi-threading.

1

El hecho de que todos digan correctamente que el multihilo es duro es muy triste. Necesitamos desesperadamente hacer que los sistemas de concurrencia sean fáciles.

Personalmente, creo que vamos a necesitar un cambio de paradigma y nuevas herramientas.

+1

desafortunadamente, así son las cosas. Las herramientas no facilitarán los hilos (ya tenemos algunos, por ejemplo, openmp o TBB). El problema es simplemente difícil. Es posible que obtengamos mejores herramientas, pero aparecerán a costa del rendimiento simultáneo para que las aplicaciones funcionen correctamente. – gbjbaanb

+0

cambio de paradigma, luego herramientas;) – Pyrolistical

15

Tienes que pensar, ¿cuáles son los beneficios reales de los hilos? Recuerde que en una máquina de núcleo único, los hilos no permiten la ejecución simultánea, solo la impresión de ello. Detrás de escena, la CPU está cambiando de contexto entre los diferentes hilos, haciendo un poco de trabajo en cada uno cada vez. Por lo tanto, si tengo varias tareas que no implican esperar, ejecutarlas al mismo tiempo (en un solo núcleo) no será más rápido que ejecutarlas de forma lineal. De hecho, será más lento, debido a la sobrecarga adicional de la frecuente conmutación de contexto.

Si ese es el caso, entonces, ¿por qué utilizar hilos en una sola máquina central? Bueno, en primer lugar, porque a veces las tareas pueden implicar largos períodos de espera en algún recurso externo, como un disco u otro dispositivo de hardware, para estar disponibles. Mientras que la tarea está en una etapa de espera, el enhebrado permite que otras tareas continúen, utilizando así el tiempo de la CPU más eficiente.

En segundo lugar, las tareas pueden tener un plazo de algún tipo para completar, especialmente si responden a un evento. El ejemplo clásico es la interfaz de usuario de una aplicación. La computadora debe responder a los eventos de acción del usuario lo más rápido posible, incluso si está ocupado realizando alguna otra tarea de larga ejecución, de lo contrario, el usuario se agitará y puede creer que la aplicación se ha bloqueado. Enhebrar permite que esto suceda.

En cuanto a los juegos, no soy un programador de juegos, pero mi comprensión de la situación es la siguiente: los juegos en 3D crean un modelo programático del mundo del juego; jugadores, enemigos, objetos, terreno, etc. Este mundo del juego se actualiza en pasos discretos, según la cantidad de tiempo transcurrida desde la actualización anterior. Entonces, si 1ms ha pasado desde la última vez en el ciclo del juego, la posición de un objeto se actualiza usando su velocidad y el tiempo transcurrido para determinar el delta (obviamente la física es un poco más complicada que eso, pero obtienes la idea). Otros factores como la IA y las claves de entrada también pueden contribuir a la actualización. Cuando todo está terminado, el mundo del juego actualizado se representa como un nuevo marco y el proceso comienza de nuevo. Este proceso generalmente ocurre muchas veces por segundo.

Cuando pensamos en el ciclo del juego de esta manera, podemos ver que el motor está logrando un objetivo muy similar al del enhebrado. Tiene una serie de tareas de larga ejecución (actualización de la física mundial, manejo de la entrada del usuario, etc.), y da la impresión de que están sucediendo al mismo tiempo dividiéndolas en pequeños pedazos de trabajo e intercalando estas piezas, pero en lugar de confiar en la CPU o el sistema operativo para administrar el tiempo dedicado a cada uno, lo está haciendo él mismo. Esto significa que puede mantener todas las diferentes tareas sincronizadas correctamente y evitar las complejidades que conlleva el enhebrado real: bloqueos, prioridad, reentrada, etc. No hay implicancia en el rendimiento de este enfoque tampoco, porque como dijimos La máquina de un solo núcleo realmente solo puede ejecutar código linealmente de todos modos.

Las cosas cambian cuando tienen un sistema multi-core. Ahora, las tareas pueden ejecutarse de manera genuina concurrente y puede haber un beneficio en el uso del subprocesamiento para manejar diferentes partes de las actualizaciones del mundo del juego, siempre que podamos sincronizar los resultados para generar marcos consistentes. Por lo tanto, esperaríamos que con el advenimiento de los sistemas multi-core, los desarrolladores de motores de juegos estarían trabajando en esto. Y así resulta, lo son. Valve, los creadores de Half Life, han introducido recientemente el soporte de múltiples procesadores en su Source Engine, y me imagino que muchos otros desarrolladores de motores están siguiendo su ejemplo.

Bueno, eso resultó un poco más de lo que esperaba. No soy un experto en juegos de rosca o juegos, pero espero no haber cometido ningún error especialmente evidente.Si lo tengo, estoy seguro de que la gente me va a corregir :)

+2

En realidad, incluso en una máquina de núcleo único, los hilos pueden tener una ganancia de rendimiento. Algunas máquinas cambian intercambiando el hilo en ejecución debido a la pérdida de memoria. Si no recuerdo mal, HyperThreading de Intel hace algo similar. –

+0

+1 para obtener una respuesta detallada –

+0

También especifico que al usar hilos no supervisa su programación con precisión. Los algoritmos de programación están diseñados por el SO, no por el desarrollador del juego. Entonces, si tiene que manejar tareas en un orden riguroso, es (al menos) más fácil hacerlo en un solo hilo. –

1

Los hilos están muertos, bebé.

Siendo realistas, en el desarrollo de juegos, los hilos no escalan más allá de la descarga de tareas muy dedicadas como la conexión en red y la carga. Los sistemas de trabajo parecen ser la única forma de avanzar, dado que 8 sistemas de CPU son cada vez más comunes incluso en PC. Y puede garantizar que los próximos sistemas súper multinúcleo como el Larrabee de Intel estarán basados ​​en el sistema de trabajo.

Esto ha sido una realización algo dolorosa en los proyectos de Playstation3 y XBOX360, y parece que ahora incluso Apple ha subido a bordo con su sistema "revolucionario" Grand Central Dispatch en Snow Leopard.

Los hilos tienen su lugar, pero la ingenua promesa de "poner todo en un hilo y todo funcionará más rápido" simplemente no funciona en la práctica.

+0

... Los hilos son un componente integral de lo que estás hablando. Está justo debajo de una capa adicional de abstracción. – colithium

Cuestiones relacionadas