El blog de Pablo Zurita.

Mayo 17, 2008

Trabajo para EA

Archivado en: General — Pablo Zurita @ 9:13 pm

Desde el ultimo post varias personas han querido saber que estoy haciendo exactamente para Electronic Arts y como me esta yendo con el trabajo. La verdad es que esta yendo todo muy bien a pesar de que hay algunas cosas a nivel de organización y procesos que podrían esta yendo mucho mejor, pero todo va mejorando poco a poco. Realmente no puedo entrar en detalles sobre el proyecto en el que estoy trabajando porque justamente tengo un NDA firmado que no me permite hacerlo. Lo que si puedo contar es que estoy trabajando para Electronic Arts en un juego todavía no anunciado oficialmente y que tienen cientos de personas trabajando en el, digamos un juego triple A. Dentro del proyecto estoy trabajando en la parte de UI cosa que desde mi punto de vista es muy fácil pero igual esta bueno porque tengo mucho que aprender para adaptarme a la forma de trabajo de Electronic Arts. Y eso va desde pequeñas como estilos de codificación hasta procesos muy importantes sobre como y cuando hacer el check-in del código (para no causarle problema al resto del equipo). Creo que poco a poco me voy a ir afianzando en el trabajo y entrando en más confianza con la gente de California y así eventualmente voy a poder trabajar en cosas mas interesantes, aunque no estoy para nada desesperado. De todas maneras una vez que me mude definitivamente a Buenos Aires y tenga todas mis cosas acá seguramente voy a integrar soporte a mi engine para Direct3D 9 y XInput para poder interiorizarme mejor con el trabajo en la Xbox 360.

Con respecto a la tecnología que estamos utilizando en el juego, es todo bastante interesante sobretodo porque hay varios proyectos utilizando lo mismo y por lo tanto hay muchísima gente compartiendo código y assets. En ese sentido se esta generando mucho código y por lo tanto un build completo puede tomar tranquilamente una hora para compilar, y muchas horas más para compilar y subir a la Xbox 360 todos los assets. Para apalear un poco ese tema desde el punto de vista del código, utilizamos IncrediBuild con un coordinador local y corremos agentes en todas las computadoras de la gente que trabaja para EA en Globant (incluso artistas). Esto permite mejorar un montón el tiempo de compilación aunque el tiempo de linking sigue siendo algo pesado. Desde el punto de vista de los assets no se puede distribuir todo ya que no se ha paralelizado las diferentes herramientas. Pero igual, tampoco es necesario hacer rebuilds de todos los assets todos los días, generalmente el fin de semana dejo generando los assets así que cuando llego el lunes al trabajo tengo todo listo. Algo que si me es molesto es tener que usar Perforce ya que no lo usaba desde el 2003 y siempre use CVS o Subversion, aunque uno de los arquitectos que trabaja en otro proyecto de EA la tiene sumamente clara con Perforce. Pero en general estoy muy conforme porque me dan todas las herramientas para trabajar de manera bien productiva y eso hace una gran diferencia. Lo único que hay que mejorar y en lo que estamos mejorando literalmente día a día es la dinámica de trabajo con la gente de California. Creo que poco a poco nos vamos ajustando bien a la forma de trabajo y va a ser posible dejar muy conforme a Electronic Arts y estar muy conformes nosotros en Globant.

Mayo 2, 2008

Síntesis de estos últimos meses

Archivado en: General — Pablo Zurita @ 1:00 am

Después de varios meses sin actualizar vuelvo a escribir para el blog. En estos meses no he trabajado demasiado en mi engine pero mi vida laboral cambio bastante a través de esos meses. Pase de trabajar de consultor a trabajar on-site. Trabaje para tres empresas diferentes en cosas totalmente diferentes. Trabaje para Visual Technologies de Inglaterra en un producto que se utiliza para visualización científica y demás, trabaje en Gameloft en juegos para celulares, y ahora estoy trabajando en Globant en proyectos para Electronic Arts.

En Visual Technologies trabaje portando un producto a Linux cosa que no fue complicado porque dentro de todo el código no era tanto para portar y porque en cierta manera no era como pasar un producto totalmente basado en tecnologías para Windows. Por ejemplo el building system ya estaba en CMake por lo tanto CMake se encargo de generar los makefiles y demás cosas necesarias para compilar aunque obviamente hizo falta modificar el script. Después de eso tuve que resolver un montón de errores de compilación por la utilización de las APIs de Windows o por código que gcc no podía compilar (porque el código no era compatible con el standard ISO C++ o por bugs de gcc). Después de bastante trabajo todo salio andando en tiempo y forma. Una vez que termino mi contrato decidí dejar de lado el trabajo como consultor para trabajar on-site en Gameloft Córdoba.

Para los que no conocen Gameloft, Gameloft es una empresa que se dedica a crear juegos para dispositivos móviles. Ahora algunos se preguntaran que estaba haciendo en Gameloft si no tenia ninguna experiencia con móviles y además la mayoría de los móviles se programan con Java. Y la verdad es que hubieron dos razones para entrar a Gameloft, primero que nada es que fui a buscar mas trabajo en grupo porque estaba cansado de trabajar de consultor solo en mi depto. La segunda razón es simplemente que las oficinas de Gameloft están literalmente a 50 metros de mi depto en Córdoba. La verdad que la experiencia con Gameloft fue muy interesante desde el punto de vista humano porque pude trabajar mas en equipo, el ambiente de trabajo era sumamente relajado y además me permitió volver a trabajar con plataformas con recursos mas limitados. La verdad es que en el inicio marchaba todo de lujo pero conforme el trabajo se volvió más repetitivo se hizo más notorio el hecho de que estaba trabajando en cosas que técnicamente no eran de mi interés. Entonces en ese momento decidí la oferta de Globant.

Aunque la mayoría conoce a Globant como la empresa que le da servicios a Google, también ahora tiene un cliente muy importante que es Electronic Arts razón por la que me hicieron una oferta de trabajo que tome. En Globant solo llevo unos días y mi rol es trabajar en un juego para la Xbox 360 pero todavía no he podido hacer demasiado. Perdí algunos días haciendo el setup del devkit de la Xbox 360, el de mi computadora que voy a usar y todavía no termine. Pero a pesar de eso ya por lo menos pude mirar un poco de código y entender lo que voy a estar haciendo. Obviamente no puedo hablar sobre lo que estoy trabajando exactamente pero lo que si puedo decir es que va a ser la primera vez que voy a estar trabajando en un juego AAA directamente en vez de trabajar en herramientas o un engine en si. Creo que la experiencia va ser muy interesante y bastante diferente a lo que estaba acostumbrado sobretodo porque a pesar de que no estoy en control del diseño del juego en si, voy a tener que pensar como mi trabajo impacta al usuario final en vez de a un artista o un programador. Igualmente todavía le estoy agarrando la mano a lo que tengo que hacer y por otra parte estoy un poco mas preocupado por otras cosas fuera del trabajo, específicamente el hecho de que tengo que encontrar un buen depto lo antes posible en Buenos Aires así ya me puedo mudar definitivamente de Córdoba.

Bueno, espero tener cosas más interesantes para contar en el futuro sobre temas técnicos en vez de tener que hacer una recapitulación de los últimos meses solo para avisar que no había muerto.

Noviembre 8, 2007

Conclusiones EVA 07

Archivado en: General — Pablo Zurita @ 12:00 am

El 4 de Noviembre presente en la EVA 07 sobre arquitecturas multihilos para motores 3D. La charla fue basada justamente en el artículo que escribí el 26 de julio pero con más información. Entre otras cosas agregue información sobre el uso e implementación de thread pools y el trabajo de implementación en Win32 y Xbox 360 entre otras cosas. La presentación la pueden bajar de acá. La charla fue muy bien en su desarrollo pero la mayoría de las preguntas que me hicieron sobre el tema tenía más que ver con temas de implementación en las plataformas y no tanto sobre la arquitectura que en mi punto de vista es lo más importante. Creo también hubo mucha gente que no tenia este tema en sus radares y por lo tanto no pudieron entender la charla pero me parece que el articulo de julio 26 les va a ayudar a entender mas sobre el tema.

Dejando el tema de mi presentación de lado, quede muy conforme con esta EVA. La calidad de las presentaciones fueron mucho mejores que las EVAs anteriores, hubo más gente, y también tuve la oportunidad de charlar con diferentes personas sobre varios temas sobre programación de engines y herramientas. Obviamente como toda charla entre programadores los tópicos pasaron de un lado a otro pero igual fue interesante ver en que estaban trabajando otras personas. Lo único que me parece que tiene que cambiar para el año que viene es que se tiene que separar la conferencia en tracks. La cantidad de asistentes es tal que me parece que ya no tiene sentido mantener a todos juntos ya que los intereses son bastante distintos para todos. Eso obviamente no quiere decir que hay que hacer 15 tracks diferentes, pero como mínimo creo que hacen falta dos tracks, uno totalmente técnico encarado a los programadores y un track artístico para los que hacen arte, música y demás. Y otra cosa que tiene que haber para la próxima EVA es un pequeño aparatito llamado presenter que haría las presentaciones mucho mas dinámicas y si cortes cuando la persona que maneja la computadora se olvida de saltar de slide o salta demasiadas. Dejando eso de lado quede muy conforme con la conferencia, realmente valió la pena el viaje de ~700KM.

Octubre 31, 2007

Charla en la EVA 07.

Archivado en: General — Pablo Zurita @ 7:43 pm

Simplemente quería avisarles que voy a estar dando una de las charlas en la EVA 07 (Exposición de Videojuegos Argentina) que se va a realizar el 3 y 4 de noviembre. La charla va a ser sobre el último artículo que escribí pero con más información. Aprovecho también para avisarles que estoy en busca de trabajo nuevamente así que voy a estar con varias copias de mi curriculum en la EVA 07 y si no me pueden pedir una copia dejando un comentario en este post.

Julio 26, 2007

Arquitectura Multihilos Para Motores 3D

Archivado en: General — Pablo Zurita @ 5:06 pm

Abstract
“Los microprocesadores de múltiples cores ya están llegando a la masas y dejaron de ser algo exclusivos de los servidores y las supercomputadoras. La mayoría de las computadoras personales y consolas de video juegos usan microprocesadores con múltiples cores que permiten ejecutar de forma paralela varios hilos de ejecución en hardware. Por otra parte la velocidad de cada core se ha estabilizado y por lo tanto no es posible mejorar la performance de ejecución de una aplicación que se ejecuta en un solo hilo de ejecución simplemente agregando más hardware. Pero crear una arquitectura para aplicaciones interactivas en 3D que usen este hardware nuevo es un reto por la necesidad de interacción entre los diferentes subsistemas. En este artículo se muestra la arquitectura que se creó para el Chromaticity Engine, un motor 3D que fue pensado para aplicaciones interactivas. El objetivo final del articulo es mostrar los diferentes inconvenientes al crear un motor 3D multihilo para aplicaciones interactivas y como se solucionaron esos inconvenientes en el Chromaticity Engine.”
Palabras Clave
Motor 3D, Engine 3D, Computación Grafica, Arquitectura, Xenon, Cell, multihilo, multithread.

Introducción
La complejidad de los motores 3D y las aplicaciones que los utilizan hacen muy difícil la separación de un motor de un solo hilo en múltiples hilos. A nivel de la arquitectura los diferentes subsistemas de un motor dependen entre sí por lo tanto hay dos maneras de encarar la arquitectura de un motor 3D. La primera es usar la misma arquitectura que se usaba cuando había un solo core y un solo microprocesador con la diferencia que se trata de crear hilos en funciones especificas. El beneficio de este método es que se puede mantener bastante código sin modificar y usar APIs (Application Programming Interface o Interfaz de Programación de Aplicaciones) como OpenMP para hacer todo más fácil. El problema con esta solución reside en que se trata de mezclar dos modelos que son fundamentalmente diferentes, el modelo de hilo único y el modelo de múltiples hilos. Este factor hace prácticamente imposible aprovechar al máximo el hardware disponible para obtener buenas ganancias de performance. El otro modelo consiste en dejar de lado la actualización serial de cada subsistema y remplazarlo por un modelo donde cada subsistema se actualiza de manera independiente pero siempre manteniendo cierta coherencia en los tiempos transcurridos en la simulación. Este modelo permite utilizar mejor los recursos disponibles en un microprocesador de múltiples cores y con una arquitectura adecuada es posible especializar para un microprocesador en específico sin requerir grandes cambios al motor entero. Este último modelo es el utilizado en el Chromaticity Engine y es el que va a ser expuesto.

Es importante reconocer también el hecho de que las arquitecturas de los microprocesadores en las diferentes plataformas difieren de manera sustancial y por lo tanto es necesario que esta arquitectura se pueda moldear para adaptarse a las diferentes plataformas. Si observamos los tres microprocesadores más importantes para aplicaciones interactivas en 3D vamos a ver grandes diferencias. Los tres microprocesadores que vamos a observar son:

  • Cell Broadband Engine de Sony, Toshiba e IBM que es utilizado en servidores y la consola PlayStation 3.
  • Xenon de IBM que es utilizado en la consola Xbox 360 de Microsoft.
  • Core 2 de Intel que es utilizado en PCs y la última serie de Macs de Apple.

Teniendo en cuenta estas diferencias se va a exponer la arquitectura y van a evaluar los casos específicos para cada microprocesador.

Microprocesadores
Las diferencias en los microprocesadores que vamos a evaluar son de gran importancia. La primera diferencia se hace ver en la cantidad de cores en los microprocesadores y las capacidades computacionales de los diferentes cores.
En el caso del Core 2 de Intel vemos un microprocesador con dos o cuatro cores, un cache L1 de 64 KB por cada core, un cache L2 compartido de 4 MB cada dos cores, ejecución fuera de orden, y un hilo en hardware por core [1, 2, 3]. Este microprocesador que es fácil de programar ya mantiene la mayoría de las características de los microprocesadores de las generaciones anteriores. Lo más importante en este sentido es que cada core mantiene la ejecución fuera de orden y que el cache L2 compartido tiene un tamaño considerable. Si analizamos esta situación podemos ver que podríamos directamente asignar un core a uno o varios subsistemas del motor hasta utilizar los dos o cuatro cores.

En el caso del Xenon de IBM vemos que es un microprocesador con tres cores, con un cache L1 de 64 KB por cada core, un cache L2 de 1 MB compartido por los tres cores y el GPU, ejecución en orden, y dos hilos simétricos en hardware por cada core [4, 5]. Aquí es importante observar el hecho de que aunque parece muy diferente al Core 2 en la arquitectura, vamos a ver que las diferencias no son tan notables que las que hay con el Cell. De todas formas hay diferencias significativas que van a impactar a la arquitectura del motor. Primeramente esta la ejecución en orden de las instrucciones lo que va a causar que si uno no organiza bien las instrucciones a ejecutar es posible perder bastante performance mientras un hilo ejecuta una instrucción intensiva. En este caso vamos a tener en cuenta la salida del compilador para ver que instrucciones generamos y crear código que sea más amigable con este factor (un ejemplo es que hay que limitar de gran manera la ejecución de funciones virtuales). Por otra parte el tamaño del cache L2 es bastante más pequeño que el cache L2 en un Core 2 pero sigue estando en los parámetros aceptables como para no hacer decisiones de gran impacto basados en el tamaño del cache L2. En general podemos decir que se va a poder asignar un core a cada subsistema aunque en este caso hay que tener más cuidado al momento de manejar la información y el orden de ejecución por las consideraciones ya mencionadas.

Por último vemos el Cell Broadband Engine de Sony, Toshiba e IBM. Este es un microprocesador con un “Power Processor Element” (“PPE”) que es encargado de controlar seis u ocho “Synergistic Processing Elements” (“SPE”). El PPE tiene un cache L1 de 64 KB y un cache L2 de 512 KB, dos hilos de ejecución por hardware, este core esta hecho principalmente para controlar los SPEs y realizar operaciones que no se subdividen bien en los SPEs. Cada SPE tiene 256 KB de memoria sin cache, tiene un modelo de ejecución en orden y un solo hilo en hardware [6, 7, 8]. Este es el microprocesador más complejo para programar. Los SPE tienen un cache muy chico lo que implica que hay que separar todos los trabajos de manera muy fina para mantener a todos los SPEs ocupado y en este caso definitivamente no es posible asignar un SPE a cada subsistema porque la combinación de cache pequeño y ejecución en orden crearían estragos desde el punto de vista de la performance. Por lo tanto hay que darle especial importancia al planificador de tareas o scheduler del motor de tal formas que los SPEs se mantengan ocupados pero sin estancarse en una tarea en particular [9].

Paralelismo
Teniendo en claro las diferencias en las diferentes plataformas es importante encontrar un modelo de paralelismo de manera que las plataformas sean bien aprovechadas sin crear una arquitectura difícil de mantener y expandir. Esto implica ignorar la posibilidad de agregar paralelismo función por función ya que las posibles ganancias de performance son muy limitadas [10]. Por otro lado tenemos que tener en cuenta que la interacción entre los diferentes subsistemas en un motor 3D es constante por lo tanto no es posible simplemente separar cada subsistema en diferentes cores como si estuvieran en el vacio (Figura 1). Dada la naturaleza de las aplicaciones interactivas hay que buscar soluciones de paralelismo que permitan la interacción entre los diferentes subsistemas sin que esto implique excesiva complejidad en mantenimiento y costo en performance.

Figura 1
Figura 1: Ejemplo de cómo es la interacción entre diferentes subsistemas de un motor 3D para aplicaciones interactivas. Como se puede ver hay dependencia entre los diferentes subsistemas hasta el momento de renderizar el video o sonido.

Uno de los modelos de paralelismo posibles implica en mantener el modelo del bucle principal de un motor 3D para microprocesadores con un solo core y simplemente paralelizar los subsistemas que no interactúan entre si [11]. Por ejemplo si tenemos un subsistema simulador de partícula entonces lo podemos mantener paralelo a la inteligencia artificial y ejecutar de manera simultánea en diferentes cores los dos subsistemas (Figura 2). Pero este modelo tiene muy pocas aplicaciones en un motor 3D para aplicaciones interactivas ya que la cantidad de subsistemas que se pueden paralizar de esa manera son limitados. En este modelo procesadores como el Cell Broadband Engine quedan esperando instrucciones para ejecutar en los diferentes SPEs pero en definitiva el 80 por ciento de los SPEs van a quedar libres. Este modelo tampoco permite da control sobre cómo se van a utilizar los diferentes cores.

Figura 2
Figura 2: Ejemplo de paralización de subsistemas independientes entre sí. En este caso solo la inteligencia artificial y el simulador de partículas son independientes entre sí por lo tanto se ejecutan de manera paralela. Pero el resto del bucle permanece en un solo core tomando la mayoría del tiempo de ejecución.

El Chromaticity Engine utiliza un modelo hibrido de paralelismo donde los subsistemas se actualizan de manera totalmente paralela siempre trabajando con la última información disponible del resto de los subsistemas, y a la vez dentro de cada subsistema otro nivel de paralelismo es posible a través de la actualización de objetos independientes dentro del subsistema en sí.

En el primer nivel de paralelismo se busca tener todos los subsistemas sean de ejecución independiente del resto de los subsistemas (Figura 3). La dependencia entre los diferentes subsistemas sigue existiendo, pero en vez de que un subsistema termine de actualizarse para pasar al siguiente, todos los subsistemas se actualizan en paralelo basado en la última información disponible. El gran beneficio de paralelizar de esta manera el motor es que se puede escalar a procesadores con múltiples cores sin problemas, es posible mantener cada subsistema en su propio core.

Figura 3
Figura 3: Ejemplo del primer nivel de paralelismo en el Chromaticity Engine. En este caso podemos ver que los diferentes subsistemas están en cores diferentes y corren de manera totalmente independiente. Al momento de actualizarse cada subsistema, la última información disponible de cada subsistema se obtiene y se utiliza.

El segundo nivel de paralelismo va al nivel de los subsistemas en sí. Dentro de un subsistema ciertas operaciones no dependen entre si y por lo tanto es posible realizar estas operaciones en paralelo (Figura 4). Por ejemplo si tenemos un subsistema de animación que va a modificar la geometría de los objetos dinámicos en una escena, es posible animar esos dos objetos de manera paralela ya que un objeto no depende del otro. Este modelo de paralelismo no es muy útil en una arquitectura como la del Intel Core 2 ya que la cantidad de cores es igual o menor que la cantidad de subsistemas en un motor en la mayoría de los casos. Pero en cambio en un microprocesador como el Cell Broadband Engine este modelo es muy importante ya que los SPEs pueden manejar muy poca información y hay varios SPEs.

Figura 4
Figura 4: Ejemplo del segundo nivel de paralelismo en el Chromaticity Engine. En este caso la inteligencia artificial global y la inteligencia artificial de dos objetos (por ejemplo, 3 personajes en la escena) se actualizan de manera paralela. Los objetos no van a actualizar siempre en el mismo core necesariamente.

Una característica que todas las plataforma van a compartir desde el punto de vista de la ejecución paralela tiene que ver con la necesidad de crear puntos de sincronización cuando la ejecución de uno o más subsistemas va mas rápido o más lento que el resto de los subsistemas. Por ejemplo si el administrador de escena no actualiza lo suficientemente rápido la posición de un generador de sonidos entonces al momento de renderizar el sonido la salida va a ser totalmente inapropiada. Por eso es necesario definir un umbral de cuadros antes de crear un punto de sincronización para que todo vuelva a estar sincronizado.

Scheduler o planificador de tareas
Dejar que cada subsistema decida que core utilizar seria una muy mala decisión de diseño. La razón es que, o el subsistema no tiene información suficiente como para tomar una buena decisión sobre que core utilizar, o la lógica sobre que hilo usar se repite a través de cada subsistema creando un gran problema de mantenimiento y performance. Por esa razón en el Chromaticity Engine hay un scheduler o planificador que se encarga de manejar todas las operaciones que tienen que ser ejecutadas en los diferentes hilos. El scheduler va a ser diferente para cada tipo de microprocesador porque por ejemplo no sería efectivo aplicar las mismas políticas de scheduling basado en un Core 2 a un Cell con ocho SPEs. En el caso del Core 2 se puede dejar un o un par de subsistemas en cada hilo y obtener una performance más que aceptable, pero en el caso del Cell el scheduler va a tener un trabajo más complejo al ir asignando diferentes SPEs a cada mini proceso en cada subsistema. También hay que tener en cuenta que el scheduler no puede crear y destruir hilos constantemente ya que bajo ninguna de las plataformas la creación y destrucción de hilos es barata. Y con respecto a la destrucción de hilos, un hilo nunca tiene que ser matado sino que ese hilo tiene que cometer un “suicidio” porque matar un hilo es una de las operaciones más costosas en todas las plataformas [12, 13]. En caso de ser necesario mantener un solo modelo de paralelismo para todas las plataformas, entonces es necesario seguir el modelo para el Cell ya que es el denominador común.

La política de scheduling para el Intel Core 2 consiste en tener los subsistemas balanceados en los diferentes hilos. Para hacer el balanceo correcto es necesario recolectar métricas de los diferentes subsistemas y hay que acomodar los subsistemas en los diferentes hilos. Uno de los problemas para lograr el balanceo correcto a través de los diferentes cores es que no hay forma de especificar definitivamente en que core correr un hilo. En Windows se puede sugerir que core usar usando la función SetThreadAffinityMask pero esto no asegura que efectivamente un hilo se ejecute en el core que queremos. Pero incluso esta práctica no es efectiva porque el entorno donde se usan los Intel Core 2 hay muchos hilos en ejecución y por lo tanto es mucho mejor dejar al scheduler de Windows manejar a que core asignar cada hilo.

La política de scheduling para el Xenon es bastante similar a la del Intel Core 2, pero hay algunas diferencias. Primero es necesario asignar específicamente que hilo en hardware usar de lo contrario todos los hilos que creamos van a estar ejecutándose en el mismo hilo en hardware del hilo que lo creo. Esto se hace usando la función XSetThreadProcessor con el argumento 0 o 1 para el core uno, 2 o 3 para el core dos, y 4 o 5 para el core tres. Salvando esta diferencia, el scheduler va a hacer básicamente lo mismo que hace para el Intel Core 2. Los subsistemas van en hilos en hardware, cualquier hilo extra puede ser insertado en cualquiera de los cores pero hay que balancear la utilización de cores.

Por último la política de scheduling para el Cell es totalmente diferente y mucho más compleja. En este caso los trabajos enviados a cada SPE van a tener que ser mucho más pequeños que mandar todo lo que hace un subsistema. Por lo tanto el scheduler va a residir en el PPE y se va a tener que encargar de que el motor use todos los SPEs. Para hacer esto el scheduler va a necesitar información en tiempo real del tiempo de ejecución de un hilo en cada SPE. Básicamente el modelo a seguir un modelo mostrado en [14] donde el scheduler tiene un queue FIFO (First In First Out) de trabajos donde los trabajos se van ejecutando en los SPEs con menos carga (Figura 5). Es muy importante que los trabajos que agreguemos al queue sean lo más atómicos posible. La razón para esto reside en el cache y capacidad de procesamiento de los SPEs. Como se vio en la sección de microprocesadores los SPEs tienen un cache pequeño y además las instrucciones se ejecutan de manera ordenada por lo que ejecutar trabajos grandes causa problemas de performance rápidamente. Lo mejor es tener los trabajos más pequeños posibles de tal manera que el SPE se libere de trabajo lo antes posible.

Figura 5
Figura 5: Ejemplo del sistema de scheduling del Chromaticity Engine. El PPE va mandando los diferentes trabajos que tiene en el queue según van completando en los SPEs.

Portabilidad y Mantenimiento
Mantener un motor 3D para múltiples plataformas es una tarea complicada en sí mismo, por lo tanto es sumamente importante diseñar el motor teniendo en cuenta la portabilidad y mantenimiento. Los entornos de desarrollo y APIs disponibles para las diferentes arquitecturas de microprocesadores que analizamos son diferentes entre sí. Por lo tanto si aspiramos a mantener la cantidad de versiones del motor 3D al mínimo es necesario crear un diseño de motor donde el código especifico para cada plataforma se mantenga lo mas separado posible del resto del motor. Por ejemplo no sería bueno tener diferentes forks o usar sistemas de defines simplemente para crear un hilo de ejecución nuevo simplemente porque las plataformas usan APIs diferentes. Es necesario abstraer todas las operaciones específicas de tal manera que el scheduler pueda crear un hilo de ejecución de manera transparente sin necesidad de saber cómo crear este hilo en la plataforma donde el motor 3D se está utilizando. Cuando todo el código esta abstraído de una manera modular es más fácil mantener una sola versión del motor, portar a otras plataformas, e incluso hace testing unitario. Obviamente esto implica tener en cuenta las diferentes APIs para las diferentes plataformas, por eso por ejemplo el soporte para la creación de hilos de ejecución se baso en Boost Threads [15]. El resultado no es una clase que soporta todo lo que una librería tendría sino que es el conjunto de operaciones mínimas para obtener los resultados deseados en todas las plataformas. Una vez que tenemos todo abstraído el resto del motor va utilizar esta capa y en ninguno de los casos va a utilizar funciones específicas a una plataforma.

Un aspecto importante a tener el cuenta es que dada la ejecución en orden del Xenon como el Cell no se va a poder usar polimorfismo para abstraer todo ya que el costo es bastante algo y en realidad no agrega nada útil para el usuario. Por lo tanto es necesario definir una manera de crear y mantener una capa intermedia que todos los modelos de creación de threads para que sea fácil de mantener. Pero a la vez, todo esto se tiene que resolver en tiempo de compilación y no en tiempo de ejecución usando funciones virtuales.

Resultados
El Chromaticity Engine fue testeado bajo diferentes plataformas aunque no pudo ser probado en todas las plataformas que se nombraron. Para probar la performance se creó una escena con 524,288 objetos dinámicos cada uno con 18 triángulos. En ningún momento se renderizo ni video ni sonido para evitar influenciar los resultados con valores que fluctúan basados en el GPU. El motor en este caso tenía que mantener un grafo de escena con toda la geometría de la escena y además el motor realizaba consultas a un octree que subdividía todo el espacio.

En la versión de PC el motor fue probado en Windows Vista en un Core 2 Duo E6700, Core 2 Quad QX6600 y AMD Athlon 64 X2 6000+. En estos casos el ganador fue el Core 2 Quad QX6600 por el uso de los cuatro cores (Figura 6). Como se menciono anteriormente, no es posible especificar con seguridad que core utilizaron cada hilo creado.

Figura 6
Figura 6: Performance de los diferentes microprocesadores en Hertz. En azul es la performance del motor corriendo con múltiples hilos, y el rojo el motor corriendo en un solo hilo.

Las ganancias en velocidad fueron notables comparado con el motor corriendo en un solo core con un solo hilo. Como se ve la velocidad en un solo hilo llega a un techo como [10] argumenta.

En la versión para el Cell Broadband Engine, el motor se corrió en una PlayStation 3 sobre Yellow Dog Linux 5.0. En este caso la diferencia entre correr usando un hilo en el PPE y un SPE, contra usar dos hilos en el PPE y los SPEs fue notable. Esto tiene que ver con el hecho de que los SPEs son sumamente especializados y con ciertas limitaciones.

Figura 7
Figura 7: Performance del PlayStation 3 Cell en Hertz. En azul es la performance del motor corriendo en el PPE y los SPEs, y el rojo el motor corriendo en un solo hilo en el PPE y usando un solo SPE.

En la versión para el Xenon no pudimos probar realmente la performance ya que para desarrollar en el Xenon es necesario tener el XDK de Microsoft que esta solo disponible para los estudios de video juegos y los creadores de middleware.

Conclusión
El Chromaticity Engine es un motor 3D que fue escrito en respuesta a los cambios en las plataformas donde tiene que ejecutarse. El cambio fundamental se produjo en los microprocesadores utilizados en estas plataformas. Se paso de disponer un solo hilo en hardware a disponer como mínimo un hilo en hardware por core con dos cores. No solo esto sino que los cores mantuvieron la misma velocidad, esto implica que ya no vamos a obtener más ganancias de performances usando un solo hilo [11]. Por eso si hay que escribir un motor 3D para aplicaciones visuales es necesario crear una arquitectura multihilo que sea fácil de mantener y portar a diferentes plataformas. Gracias a los modelos de paralización y la arquitectura expuesta en si es posible escribir motores 3D que aprovechan las arquitecturas de los diferentes microprocesadores sin necesariamente crear un motor sumamente complejo y complicado de mantener.

A futuro va a ser necesario validar mejor la arquitectura ya que la arquitectura expuesta fue probada en una pequeña cantidad de plataformas. En especial hay que analizar el trabajo desde el punto de vista de las plataformas para visualización científica donde las necesidades de visualización no son necesariamente diferentes pero las plataformas donde corren son totalmente diferentes.

Referencias
[1] O. Wechsler. Inside Intel® Core™ Microarchitecture: Setting new standards for energy-efficient performance, 2006.
[2] J. Doweck. Inside Intel® Core™ Microarchitecture and Smart Memory Access: An in-depth look at Intel innovations for accelerating execution of memory-related instructions, 2006.
[3] R.M. Ramanathan. Intel® Multi-Core Processors: Making the move to Quad-Core and beyond, 2006.
[4] J. Brown. Application-customized CPU Design: The Microsoft Xbox 360 CPU story, 2005.
[5] J. Andrews, N. Baker. Xbox 360 System Architecture. IEEE Micro Volume 26, Issue 2, 2006.
[6] M. Gschwind, H. P. Hofstee, B. Flachs, M. Hopkins, Y. Watanabe, T. Yamazaki. Synergistic Processing in Cell’s Multicore Architecture. IEEE Micro Volume 26, Issue 2.
[7] J.A. Kahle. Introduction to the Cell Multiprocessor, 2005.
[8] D. Pham. The Design and Implementation of a First Generation Cell Processor, 2005.
[9] D.A. Brokenshire. Maximizing the Power of the Cell Broadband Engine Processor: 25 tips to optimal application performance, 2006.
[10] H. Sutter. A Fundamental Turn Toward Concurrency in Software. Dr. Dobb’s Journal, 2005.
[11] A. El Rhalibi, D. England, S. Costa. Game Engineering for a Multiprocessor Architecture, 2005.
[12] B. Dawson. Coding For Multiple Cores on Xbox 360 and Microsoft Windows, 2006.
[13] Cell Broadband Engine Programming Handbook, 2006.
[14] D. Mallinson, M. DeLoura. CELL: A New Platform for Digital Entertainment, 2005.
[15] W.E. Kempf. The Boost C++ Libraries: Boost Threads, 2003.

Octubre 4, 2006

Herramientas.

Archivado en: General — Pablo Zurita @ 8:01 pm

Desde esta generación de motores en tiempo real nos podemos dar cuenta que ya no es posible diferenciaros a nivel técnico. La llegada de GPUs programables con lenguajes de alto nivel nos pone a todos en una situación similar. Escribiendo shaders y manipulando sus parámetros logramos obtener el aspecto visual de casi cualquier aplicación creadas por programadores conocidos como John Carmack o Tim Sweeney. Ya no hay necesidad de crear complicadas estructuras de datos, hacks complicados, y demás para lograr un aspecto visual definido. Esto demuestra un par de cosas. Primero, nunca fue tan fácil trabajar en computación grafica. Y segundo, para diferencia nuestro producto del resto vamos a depender en nuestros artistas y por consecuencia de ello, vamos a depender en las herramientas que les demos a nuestros artistas. Por eso va a ser muy importante darles herramientas que sean flexibles, fáciles de usar, y hacer todo en un tiempo razonable.

En el pasado estábamos acostumbrados a crear herramientas muy limitadas porque los recursos eran limitados. Por ejemplo en la era del Quake 2 tenias editores simples como el Qoole para la edición de geometría, las texturas eran de 256 colores creadas con editores como Wally, y a nivel técnico el aspecto visual era determinado por una simple modulación entre las texturas difusas y los lightmaps generados por q2rad. Ahora con los GPUs programables y su gran velocidad ya no hay necesidad de limitar la tecnología y los artistas. Lentamente con el progreso de los GPUs fuimos dejando Wally por editores como Photoshop, los editores de geometría se volvieron más complejos, y los sistemas de materiales e iluminación pasaron a ser más extensos y a tener en cuenta otros componentes como nivel de especularidad y demás. Ahora nos encontramos con la posibilidad de mostrar mucha geometría, tener texturas de alta resolución (o sintetizar texturas si así lo deseamos), y los sistemas de materiales e iluminación pueden ser tan diferentes y complejos como los shaders que podemos escribir. Por eso tenemos que crear herramientas que sean flexibles para que los artistas puedan utilizar todos los recursos disponibles. Estas herramientas tienen que ser tan flexibles como los shaders que podemos correr y la geometría que podemos mostrar. Además nuestras herramientas tienen que estar muy integradas con nuestro motor para que los artistas puedan ver exactamente como el usuario va a ver el contenido. De esa manera, por ejemplo los editores de shaders como FX Componer y RenderMonkey quedan descartados. Mirando desde el punto de vista de los materiales no es posible darles un editor de texto para que escriban shaders porque eso crearía un gran gasto de tiempo y dinero en capacitación. Es necesario crear un entorno donde el artista pueda aprovechar las capacidades de los shaders pero a la vez que sea una herramienta visual que el artista pueda entender. Una posible solución es lo que hizo Epic Games con su editor de materiales. Los materiales y shaders en el Unreal Engine 3 son creados en un editor por módulos como el Reaktor. Los módulos son creados por los programadores y los materiales son creados por el artista conectando esos módulos. Si uno crea módulos bien chicos y específicos es posible darle la chance al artista de crear shaders complejos sin necesidad de ver una sola línea de HLSL o glSlang. Y a la vez esto nos da más tiempo a los programadores porque todo el trabajo recae en los artistas.

Reaktor
Síntesis de sonido por módulos en Reaktor.Unreal Material Editor.
Editor de materiales del Unreal Engine 3. Diferentes módulos son conectados para obtener el resultado final.

Por otra parte, es sumamente importante mantener las herramientas fáciles de usar. Como todo programa la usabilidad es sumamente importante. Si creamos una herramienta complicada (como el Sapien de Bungie) vamos a perder productividad, vamos a frustrar a los artistas, y se nos va a ser innecesariamente complicado integrar nuevos artistas a nuestro proyecto. También es muy importante mantener la calidad de la usabilidad durante todo el proyecto porque las posibilidades de un gran cambio de paradigma en la creación de contenido es muy poco probable en el futuro cercano. Personalmente no preveo un cambio importante en la creación de contenido hasta que pasemos a usar voxels en vez de polígonos. También es importante mantener un buen estándar de usabilidad porque generalmente nos vemos forzados a incluir nuevos artistas a nuestros proyectos que ya están en marcha por lo tanto es necesario que este nuevo integrante de nuestro equipo como miembro productivo del proyecto lo antes posible. Teniendo en cuenta esto nos podemos dar cuenta que hay un problema en general en la mayoría de los engines y soluciones actuales, y es que los estudios no están aprovechando las aplicaciones que sus artistas ya conocen. Por ejemplo, en vez de aprovechar las aplicaciones de edición de geometría como 3ds Max hay estudios que todavía siguen haciendo editores propios como D3Radiant o UnrealEd. Algunas generaciones atrás estos editores eran necesarios porque la tecnología donde corrían también era limitada, pero ahora nuestros motores son muchos mas flexibles y al final terminamos duplicando funcionalidad que ya esta disponibles en otros editores como 3ds Max o SoftImage. Esto significa que no solo los programadores pierden tiempo duplicando funcionalidad ya disponible en otros editores, sino que también los artistas pierden tiempo en capacitación para usar las herramientas nuevas. En cambio podríamos utilizar los sistemas de plug-ins para expandir estos editores según nuestras necesidades. Obviamente si tomamos esta decisión tenemos que crear los plug-ins de tal manera que mantengan la forma de trabajo del editor que estamos expandiendo. Con respecto a la usabilidad recomiendo el libro About Face 2.0 : The Essentials of Interaction Design de Alan Cooper y Robert Reimann (ISBN 0764526413).

Bugie's Sapien
Sapien de Bungie. Un test de usabilidad demostraría que esta interfaz sobrecarga al usuario con información.

Justamente la necesidad de realizar todo en un tiempo razonable puede ser la razón por la que expandir un editor existente puede ser una opción buena. Crear las funciones más básicas de edición implica un tiempo razonable, y después los sistemas más avanzados pueden ser más complicados (como por ejemplo la edición de geometría con bezier patches). En cambio realizando plug-ins toda esa funcionalidad esta disponible, por lo que nosotros no tenemos que encargar de desarrollar la funcionalidad que es especifica a nuestra tecnología. Algunos podrán decir que esto puede ser malo porque realmente no tenes el control de las herramientas, pero en definitiva tenemos que tener en cuenta cuales son las prioridades. Otros tendrán problemas con los SDKs de los diferentes productos (por ejemplo el SDK de 3ds Max es horrible) pero hay que ver desde el punto de vista de los beneficios. Y aunque nos tome tiempo adaptarnos a un SDK y entorno al que no estamos acostumbrado, ese costo siempre va a ser menor que crear una herramienta nueva e instruir a los artistas sobre su uso. El único problema con hacer esto es que si pensas hacer un producto modificable como los mods para Quake, se vas a poner una barrera. Los costos de estas aplicaciones de edición son bastante altos para que un usuario estándar.

Septiembre 5, 2006

Chromaticity Engine y Managed Code.

Archivado en: General — Pablo Zurita @ 5:09 pm

Este es el podcast número cinco de 19 minutos. En este podcast hablo sobre el estado actual del engine, y también hago uno comentarios sobre managed versus unmanaged code.

Pueden bajar el podcast desde http://www.pablo-zurita.com.ar/podcasts/PodcastManaged.mp3

Chromaticity Engine - Material test

Agosto 16, 2006

Podcast - Chromaticity Engine Kernel + Carmack @ QuakeCon.

Archivado en: General — Pablo Zurita @ 5:23 pm

Acá esta el podcast numero cuatro de 35 minutos, en este podcast hablo sobre el estado actual de engine, el kernel del Chromaticity Engine y unos comentarios sobre el speech que dio John Carmack en QuakeCon 06.

Pueden bajar el podcast desde http://www.pablo-zurita.com.ar/podcasts/ChromaStateAgile.mp3

PD: Para los que se preguntaban porque no había actualizado el blog antes, es porque estuve dos semanas de vacaciones en Cutral-Co, Neuquen, Argentina.

Julio 21, 2006

Podcast – Estado del Chromaticity Engine y Test Driven Development.

Archivado en: General — Pablo Zurita @ 7:42 pm

Acá esta el tercer podcast de 12 minutos, en este podcast hablo sobre el estado actual de engine y sobre el uso de Test Driven Development.

Pueden bajar el podcast desde http://www.pablo-zurita.com.ar/podcasts/PodcastTDD.mp3

PD: UnitTest++.

Julio 8, 2006

Podcast - Chromaticity Engine Documentacion.

Archivado en: General — Pablo Zurita @ 9:35 pm

Después de un buen éxito con el primer podcast, aquí esta el segundo podcast de 18 minutos en la pagina. En este caso hablo sobre como pienso realizar la documentación del Chromaticity Engine.

Pueden bajar el podcast de http://www.pablo-zurita.com.ar/podcasts/ChromaDocu.mp3

Entradas siguientes »

Gestionado con WordPress