PDA

Ver la versión completa : memcpy, Mhz y fps



Salustian
27/06/2005, 10:05
Hola,

he realizado un test para comprobar la rapidez de diferentes funciones para
copiar bloques de memoria. En concreto, las funciones testeadas son:

-Dos para borrar la pantalla:
GpRectFill16: del SDK oficial
gp_memset: del SDK oficial

-Cuatro para copiar el contenido de una imagen a un buffer de imagen
GpBitBlt16: del SDK oficial
asm_memcpy: memcpy hecho en ensamblador de la página de PEA
FastMemoryCopy: memcpy hecho en C por TheNestruo
gm_memcpy: del SDK oficial.

El test consiste en durante 10 segundos escribir completamente sobre
un buffer, contando el número de cuadros que se dibujan.

He obtenido los siguientes resultados:
(siempre en formato gráfico de 16 bits)

-------------------------66MHz------------------133MHz------------------166MHz
GpRectFill16 ------------------44,1 fps ------------------140,8 fps------------------161,3 fps
gp_memset------------------43,4 fps------------------132,3 fps------------------186,7 fps
GpBitBlt16------------------44,1 fps------------------56,6 fps------------------92,7 fps
asm_memcpy------------------43,9 fps------------------56,5 fps------------------92,7 fps
FastMemoryCopy ---------------44,0 fps------------------56,5 fps------------------92,7 fps
gm_memcpy------------------44,0 fps------------------56,5 fps------------------92,6 fps

Lo primero que me ha sorprendido es la baja tasa de fps. No hago más que copiar
una imagen y a 66MHz (que tengo entendido que es la velocidad natural de GP32)
apenas hay 44 fps. Y a 133 solo 56... ¿cómo se consiguen tasas de 60 fps?

También me sorprende como se comportan las funciones GpRectFill16 y gp_memset a
diferentes velocidades. Además, a doble velocidad no tengo doble número de fps. ¿¿¿???

Y por último... en gp32x.com se aseguraba que el memcpy escrito en ensamblador
era mucho más rápido... sin embargo da igual cual se use ¿¿¿???

¿Algún comentario? ¿El test que he hecho es correcto?

Os incluyo los fuentes del test y un ejecutable del mismo que funciona a 66MHz.

Un saludo al grupo.

kmkzk
27/06/2005, 10:09
Interesante test. A mi los FPS me parecen bastante iguales, imaginaba que habria mas diferencias entre las diferentes funciones testeadas.
Tambien me ha sorprendido que el gm_memset, sea inferior a GpRectFill en las primeras dos velocidades, y luego sea mas rapida a 166Mhz. Siempre creí que GpRectFill apestaba muchisimo X)

Wave
27/06/2005, 12:45
En 8 bits conseguiras el doble de fps. Asi se llega a 60fps.

oankali
28/06/2005, 08:28
Tengo entendido que las funciones del SDK tienen en cuenta el refresco de la pantalla. Sobretodo GpSurfaceFlip(). Por eso obtienes resultados similares y que luego te encuentras con saltos abismales.

Me explico. Imaginemos que el tiempo entre cada refresco de pantalla sea de 20 ms.
Si tu proceso tarda menos de 20 ms, al llamar GpSurfaceFlip(), esta esperará a que se completen los 20 ms con lo que tus FPS llegaran a 1000/20 = 50.
Si tu proceso tarda 21 ms, GpSurfaceFlip() esperará el segundo refresco de pantalla, o sea 40 ms con lo que tus FPS llegaran a 1000/40 = 25.

Por eso, cuando hago algun test de velocidad para mis funciones, lo que mido es el tiempo real de mis funciones sin utilizar GpSurfaceFlip().

Por ejemplo tu ensayo de GpRectFill16() lo cambiaría a:



num_frames_GpRectFill16 = 0;
tiempo_fin_ensayo = gp_getRTC() + tiempo_ensayo*64;

while(gp_getRTC() < tiempo_fin_ensayo)
{
GpRectFill16(NULL,&(GFX_Data.gtSurface[GFX_Data.giSurface]),
0,0,GPC_LCD_WIDTH,GPC_LCD_HEIGHT,RGB(0,31,31));
num_frames_GpRectFill16++;
}
FlipBuffer(&GFX_Data);

Prueba a hacer los mismos tests de esta manera, a ver que te sale.
Oankali

Salustian
28/06/2005, 08:41
Gracias por el apunte Oankali. Lo cierto es que así se explicarían las coincidencias entre la velocidad de las distintas funciones. Hasta esta tarde no lo podré pobrar en la consola, mañana os contaré los resultados.

Por cierto... ¿alguien sabe ese tiempo de refresco de la pantalla? ¿es configurable?

Un saludo al grupo.

mortimor
28/06/2005, 13:26
Si es configurable, tecnicamente va deacuerdo con los parametros que se le pasan al cambiar la frecuencia de la CPU (no recuerdo con cual). Pero se puede configurar directamente modificando este registro volatile long* lcdcon1 = (long*)0x14a00000;, mira los ejemplos de MrSpiv y veras que se pueden conseguir 60 fps facilmente y a 16bits.

oankali
28/06/2005, 13:51
Y yo pregunto, ¿es realmente necesario conseguir los 60 FPS?

Que sepa yo, las películas van a 25 imágines por segundo, y los dibujos animados normalillos van por los 16.
¿Realmente se nota la diferéncia entre 40 y 60 FPS?

Para lo único que realmente le veo la utilidad es para los scrolls de pantalla ya que queda mejor desplazarse 60 veces de 2 píxeles, que 40 veces de 3 píxeles si queremos conseguir una velocidad de 120 píxeles por segundo.

Salustian
28/06/2005, 15:26
Hombre, mi intención no es tener 60 fps, pero lo que me chocó es que simplemente dibujando la pantalla no los alcanzase.

Aunque reconoce que cuantos más fps mejor :)

oankali
29/06/2005, 08:07
Reconocido.

Salustian
29/06/2005, 09:01
Resultados del test de las siguientes funciones:


-------------------------66MHz--100MHz--133MHz--166MHz
GPRectFill16------------2668---3903---5253---6629
gm_memset------------2890---4194---5627---7083
GpBitBlt16---------------741----1084---1518---1954
asm_memcpy-----------740----1082---1507---1940
FastMemoryCopy-------741----1085---1515---1948
gm_memcpy------------746----1091---1522---1961

Lo medido es el número de veces que se ejecuta la función en 10 segundos, moviendo el equivalente a la memoria necesaria para una pantalla de la GP32 a 16 bits (320*240*2 bytes).

Ejemplo de código para la función GpBitBlt16 (ídem para el resto):


num_frames_GpBitBlt16 = 0;
tiempo_fin_ensayo = gp_getRTC() + tiempo_ensayo*64;

while(gp_getRTC() < tiempo_fin_ensayo)
{
GpBitBlt16(NULL,&GFX_Data.gtSurface[GFX_Data.giSurface],0,0,320,240,
(unsigned char *)fondo,0,0,320,240);
num_frames_GpBitBlt16++;
}

Ahora los resultados me parecen más lógicos, aunque no me explico cómo es posible que todas las funciones para copiar memoria den un rendimiento casi idéntico ¿¿¿???

En la página de PEA se asegura que el memcopy en ensamblador es varias veces más rápido que el del SDK oficial, sin embargo este último es ligeramente mejor que el resto.

El memcpy de theNestruo no tiene nada que envidiarle al resto.

También he hecho las mismas pruebas habilitando la caché de alineamiento, que según se dice en el proyecto del MAME de Franxis (recomiendo su lectura) acelera la GP32, pero no se ha notado, dando valores prácticamente idénticos.

¿Algún comentario? ¿A alguien se le ocurre otra forma de medir la velocidad de las funciones?

Un saludo al grupo.

Franxis
29/06/2005, 21:15
Hombre, es muy interesante esto...

El problema de utilizar gm_memset() ó gm_memcpy() es que se puede saturar el bus con la memoria de la consola y pueden empezar a aparecer scanlines verticales y fallos con el sonido...