lunes, septiembre 28, 2009

Project

Bueno vamos a continuar con el tostón este, tras un ultimatum (acaba que te piras XD) me estoy poniendo seriamente las pilas en el proyecto.

He paralelizado ya bastante cosas, aunque ahora me estoy calentando la cabeza con otras diversas, que probablemente tenga que implementar todas y hacer test con cada una.

Hay algunas que no voy a tocar, os explico. El programa usa para la lectura de las escenas un lenguaje que he creado, no uso yac ni lex, pq la escena quiero que se cree "integramente" en cada pc, en vez de tener que crear todos los datos en un pc y reenviarlo o tener que mandar la información a cada nodo del cluster. Los ficheros de configuración ocupan relativamente poco (como bien comprenderéis los hago a mano y con cierta imaginación así que no voy a meter millones de luces cada una con sus datos), así que puedo permitir hacer lo siguiente:

Nodo Padre Lee Fichero Desde Disco Duro -> "Virtualiza" Fichero -> "Comprime fichero" -> Manda a cada nodo del cluster -> "Descomprimen fichero" -> Cada nodo Interpreta la información.

Lo de comprimir y descomprimir es una idea que se me lleva pasando por la cabeza y la verdad no es descabellada ver si el fichero ocupa mucho (kb) y mandarlo comprimido, a día de hoy no esta en el diagrama de flujo final.

Lo gracioso que tiene esto es por ejemplo los ficheros de formas, texturas, etc. Gracias al formato de "virtualizacion" que he creado podemos leer los ficheros como si fueran "propios", es decir leerlos que lo hará sin problema y los tratará como ficheros con privilegio de solo lectura si fueran locales. Mediante la clase FicheroMem... Personalmente creo que debo mejorar ciertos aspectos de esto, la idea es muy buena y esta perfectamente implementada(no da errores de memoria, todo se limpia en cada nodo individualmente,etc) pero tiene fallos conceptuales, es decir, solo funciona bien cuando se hace una peticion COMUN GLOBAL a un fichero, podria por ejemplo activar flags de estado indicando si es global o no y tener una hebra en segundo plano funcionando encargada de lectura de ficheros desde el disco duro por parte del nodo maestro que se encargue de disponer los ficheros según tenga peticiones, ese proceso sería un pelín más complejo pero bastante mas versatil pudiendo leer en cualquier momento ficheros desde cualquier nodo. Para ello bastaría crear un comunicador independiente por ejemplo COM_FILES y tener a la hebra encargada de ello escuchando peticiones por ejemplo el pseudocodigo que se me ocurre:

Previo:

Inicialización del comunicador de ficheros por parte de los nodos.
Inicialización de la hebra de gestión de ficheros por parte del nodo maestro.

Hebra de gestión: (Todas las operaciones de comunicación se realizan mediante el comunicador de ficheros)

While NoFinPrograma
LecturaNoBloqueante; // comprobamos si hay peticiones de lectura
if HayPeticionLectura
if PeticionGlobal
LeeFichero y virtualiza
Realiza broadcast
else PeticionIndependiente
LeeFichero y virtualiza
Realiza envio individual
else sleep de la hebra de 0.1 segundos

Como vemos la idea sería simple elegante y sobretodo versátil, añadiría una potencia muy grande al programa incrementado sólo un poco su complejidad. Esta misma idea tengo pensada para uno de los métodos de paralelización del renderizado que ahora comentare.

Bueno sobre el renderizado, estoy estudiando como paralelizar cosas como el kdtree y el photon mapping. El primero depende claramente de la complejidad de la escena, mientras que en dragon me tarda como 2-3 minutos en construirme el kdtree, en bunny me tarda pocos segundos. Su paralelización es bastante compleja, me explico un kdtree es como un bsp pero en vez de 2 dimensiones son 3 y ademas uso heurística de voxel para calcular el corte, el paralelizado de este algoritmo presenta como incoveniente la recursividad del mismo, es un algoritmo recúrsivo y por lo tanto su paralelización puede suponer un gran problema, podría por ejemplo, crear el árbol hasta el nivel de paralelizaje apto para el número de nodos que dispongo y una vez allí enviar las ramas correspondientes a cada nodo con etiquetas para su reconstrucción posterior en cada uno. Para ello un comunicador propio por ejemplo COM_KDTREE que se encargue en esto y desarrollar el arbol hasta un nivel A = Num nodos y enviar cada rama.

El photon mapping presenta como problema la comunicación >.<, lanzamos muchisiisisisisisiismos fotones, imaginad sobre que se puede dar veces de un millon o cosas por el estilo, así que si para cada photo debo hacer una comunicación entre nodos puede ser un caos enorme. ¿Pq no haces paquetes y los envias? pues simple, se requiere saber si el photon anterior ha sido aceptado o no, tiene un método de seguridad para evitar overflow y cosas por el estilo así que comprueba continuamente el número de fotones aceptados etc. >.< quiero paralelizarlo pq en algunas escenas puede llevarme como 10 minutos, otra solución es coger al cluster más potente y encargarle a él la tarea y que el resto esperen y se lo envíe.

El renderizado estoy estudiando variantes que voy a tener que programar todas XD, la más simple es dividir la imagen en el número de nodos que hay encargar el renderizado de manera individual y juntarlo posteriormente, esto se puede hacer por filas y por columnas, también lo haré por porciones(esta opción es bastante más dificil de programar, necesita peticiones tipo los ficheros con comunicador propio). La más "pro" y que voy a mandar a tomar porculo directamente es estudiar la densidad y complejidad del kdtree según nuestra visión y dividir esa zona entre más clusters y las zonas menos densas entre menos pcs. Las primeras las tengo sobre papel y estoy viendo que partes adicionales de las que ya dispongo debo modificar para que no reviente esto xD.

Antes de nada quiero hacer una versión final secuencial pq será la que compilaré para probar la secuencial ya que lo que voy añadiendo ya es para paralelización y está metiéndole mucho código inútil.

Como podéis comprobar, this is serious business.