Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Optimizar recursos

Iniciado por bnl, 14 de Mayo de 2013, 06:09:57 PM

« anterior - próximo »

bnl

Buenas

Estoy haciendo un sistema de particulas. Lo estoy desarrollando en C# aunque probablemente en el futuro lo migre a java para usarlo en dispositivos Android con la consiguiente limitacion de recursos.

Me gustaria optimizar el consumo de recursos (procesador y memoria) del sistema de particulas.

Lo mas comodo creo que seria tener un List<Particula> y en esa lista ir añadiendo las nuevas particulas o quitando aquellas que dejen de estar vivas. Pero no creo que sea lo mas eficiente, tanto por la gestion de la lista como por el hecho de estar instanciando continuamente nuevos objetos del tipo particula.

Una opcion que se me ocurre seria manejar un pool de particulas (un array) para no tener que estar continuamente instanciandolas. Cada particula tendria un flag "Activo" y cuando haya que crear una nueva particula se reutilizaria una de las que tuviera la variable activo a false. El array se dimensionaria con el numero maximo de particulas que se considere que pueden existir simultaneamente.

Inicialmente no se crearian todas las paticulas del array si no que ser irian instanciando segun se necesitasen.
Este enfoque tiene la limitacion de que el numero maximo de particulas no variaria dinamicamente si se precisara crear mas particulas de las que admite el tamaño del pool.

Tambien si el numero de particulas que estan activas simultaneamente es muy inferior al tamaño del pool se estaria ocupando memoria innecesareamente.

¿Que enfoque os parece el mas adecuado?
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

TrOnTxU

Yo lo que hago como puse en el post de particulas del typhoeus es crear un array con un numero maximo de particulas definido en el sistema: http://typhoeus-sdk.blogspot.com.es/2012/06/problemas-de-memoria-no-lo-se-no-me.html

La versión más optimizada es la version en "C puro" con arrays estáticos.

Añado nuevas particulas al final del array, y elimino particulas con "swap-last". El máximo tamaño del Array determina el maximo numero de particulas a crear.

Crear el array de un tamaño máximo, utilizando un contador de elementos te asegura que no va a haber malloc/free (o el equivalente en garbage collection) por más que se creen y destruyan particulas cada frame.

Lo de utilizar un pool no es mala idea tampoco.

Para utilizar "z-sorting" (por ejemplo) utilizo un array de indices, esto implica un indireccionamiento más (el z-sorting solo es necesario al hacer el render no al actualizar), pero evita tener que mover estructuras o varios datos( depende de si es "SoA" o "AoS" ) por particula al ordenar.

Un saludo
Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

bnl

Gracias.
¿en que consiste lo del "swap-last"?
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

TrOnTxU

Swap-Last es cambiar el elemento a borrar por el el ultimo del array y decrementar el numero de elementos.

Este trozo de la implementacion (del código del post que puse) ...

...
  const unsigned int kEraseArraySize = 10;
  unsigned int eraseArray[kEraseArraySize];
  unsigned int eraseArrayCount = 0;

  for(unsigned int i = 0; i < pEmitter->particleCount; i++)
  {
    // Apply gravity
    add_vec3(&velocityArray[i], &velocityArray[i], &dtGravity);
    // Apply movement
    Vec3 deltaVel;
    scalar_mult_vec3( &deltaVel, &velocityArray[i], dt );
    add_vec3(&positionArray[i], &positionArray[i], &deltaVel);
    // Decrease life
    lifeArray[i] -= dt;

    if (lifeArray[i] <= 0.0f && eraseArrayCount < kEraseArraySize)
    {
      eraseArray[eraseArrayCount] = i;
      eraseArrayCount++;
     }
  }

  while (eraseArrayCount > 0) // && pEmitter->particleCount > 0)
  {
    eraseArrayCount--;
    pEmitter->particleCount--;
    // Erase and swap-last
    int eraseElement = eraseArray[eraseArrayCount];
    positionArray[eraseElement] = positionArray[pEmitter->particleCount];
    velocityArray[eraseElement] = velocityArray[pEmitter->particleCount];
    lifeArray[eraseElement] = lifeArray[pEmitter->particleCount];
  }
...

... corresponde al metodo de actualización.

1) En el array auxiliar "eraseArray" pongo hasta un máximo de diez particulas a eliminar durante ese frame (particulas que han (muerto").
2) Después del loop principal por todas las particulas, hay otro loop por las particulas "muertas", y se van intercambiando las posiciones del array (yo tengo las propiedades como "SoA") por las ultimas y decrementando el numero de particulas.

Es solo una forma de implementarlo, si utilizas algun tipo de indexacion (para luego ordenarlas) puedes tener que evitarte copiar todas la estructura o la propiedades por separado, y solo mover el indice.

De todas formas esta implementación la hice como ejemplo. El "verdadero" subsistema de particulas y efectos del typhoeus es un poco más complicado. Y el algoritmo de actualización es un poco diferente, a ver si puedo hacer otro post con imagenes del sistema y algun trozo de código de ejemplo.

Un saludo, espero que te sirva :)
Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

bnl

Gracias.
Muy interesante lo del swap last, no se me habia ocurrido.

Se me ocurre que podrias prescindir de la lista de particulas y tener solo un array con todas las particulas, tanto las vivas como las muertas. Las muertas estarian todas al final y las vivas al principio y se mantendria una variable con la posicion de la ultima particula viva. Al actualizar las particulas si una pasa a estado muerto se haria el swap con la ultima particula viva y ser decrementaria la variable de la posicion de la ultima particula viva
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

TrOnTxU

Cita de: bnl en 16 de Mayo de 2013, 11:31:02 PM
Gracias.
Muy interesante lo del swap last, no se me habia ocurrido.

Se me ocurre que podrias prescindir de la lista de particulas y tener solo un array con todas las particulas, tanto las vivas como las muertas. Las muertas estarian todas al final y las vivas al principio y se mantendria una variable con la posicion de la ultima particula viva. Al actualizar las particulas si una pasa a estado muerto se haria el swap con la ultima particula viva y ser decrementaria la variable de la posicion de la ultima particula viva

Exacto, esa es la idea.

Yo utilizo la lista de erase para acumular todas las particulas que "deben ir al final" (o sea las que se mueren) durante el ciclo de update. Pero la idea es esa, un array con el maximo de particulas, y un indice que separa las "vivas" de las "muertas" :)
Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

bnl

Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.