Ver la versión completa : Usar integers en lugar de floats
Buenas.
Estoy empezando un juego de naves y tengo previsto, entre otras cosas, que el moviento de algunos sprites tenga inercia y que, bajo ciertas circunstancias haya gravedad, por lo que les he añadido aceleración. De momento, esa aceleración la he implementado usando floats, y funciona perfectamente tanto en Windows como en la consola, pero me da que usar este tipo de datos va a hacer que todo vaya más lento cuando haya cientos de sprites en pantalla simultáneamente. Que sería más rápido si trabajara directamente con integers.
Sea o no más rápido, sé que hay una manera de simular floats con integers y tengo curiosidad por saber cómo. De hecho, leí algo al respecto hace tiempo en los foros de GP32x pero lo olvidé rápidamente ya que en ese momento no lo necesitaba para nada. Y ahora que me interesa, lo he buscado y no hay manera. Sé que eso tiene un nombre en inglés, pero no recuerdo cuál. ¿Alguien tiene idea de cómo hacerlo, me puede pasar un enlace o sabe el término correcto para buscarlo en esos foros o en el Google directamente?
Aprovecho también para preguntar si en SDL hay alguna redefinición del tipo de datos float, como lo hay del tipo de datos integer (Uint8, Sint8, Uint16, Sint16, ...). En la documentación no he encontrado nada.
Saludos.
A.r.R.c.H.E.r
31/12/2005, 07:27
Muy buenas, como bien dices utilizar float es algo lento en la GP32 y GP2X ya que no cuentan con FPU que es la encargada de hacer las operacioones de coma flotante... pero puedes utilizar punto fijo para simular los float siendo esto mucho mas rapido... no tiene la misma precision pero es bastante mas rapido, yo utilizo las math-sll que estan escritas directamente en asm para ARM y son rapidisimas aqui te las dejo para que te las descargues y le eches un vistazo.
Un saludo!
Muy buenas, como bien dices utilizar float es algo lento en la GP32 y GP2X ya que no cuentan con FPU que es la encargada de hacer las operacioones de coma flotante... pero puedes utilizar punto fijo para simular los float siendo esto mucho mas rapido... no tiene la misma precision pero es bastante mas rapido, yo utilizo las math-sll que estan escritas directamente en asm para ARM y son rapidisimas aqui te las dejo para que te las descargues y le eches un vistazo.
Un saludo!
Solamente añadir, por si acaso alguno no lo sabeis, que estas rutinas de uso de floats mediante enteros estan incluidas de serie en el devkitarm r15 o superiores y devkitgp2x, las distribuciones que usan GCC 4.0 o superior, por lo que en teoria no hace falta hacer uso de ellas explicitamente, el propio compilador hace uso de algo similar de forma transparente.
(en gcc se pone -msoft-float y ya está, A.r.R.c.H.E.r pruébalo, pero estoy casi seguro)
saludos.
¡Muchas gracias! :brindis: Mira que era fácil: "punto fijo" en lugar de "punto flotante". Buscando "fixed point math" en Google aparecen un montón de artículos.
Respecto a las math-sll tienen muy buena pinta. Además, por lo que veo, también hay funciones trigonométricas. A parte del de ARM, también usan ensamblador del 386, ¿no?
Lo dicho, muchas gracias.
Solamente añadir, por si acaso alguno no lo sabeis, que estas rutinas de uso de floats mediante enteros estan incluidas de serie en el devkitarm r15 o superiores y devkitgp2x, las distribuciones que usan GCC 4.0 o superior, por lo que en teoria no hace falta hacer uso de ellas explicitamente, el propio compilador hace uso de algo similar de forma transparente.
(en gcc se pone -msoft-float y ya está, A.r.R.c.H.E.r pruébalo, pero estoy casi seguro)
saludos.
Pues no tenía ni idea. Muchas gracias. Yo ahora mismo compilo desde Windows con devkitGP2X, pero no sé qué versión de gcc/g++ utiliza. Si escribo arm-linux-g++ --help no aparece la versión y no he encontrado ningún parámetro para saberlo. Por lo que interpreto de lo que dices, ese devkit ya lo lleva incorporado, ¿no? Bueno, al menos he probado a compilar con -msoft-float y al menos no se queja. Voy a probar con una demo de sistema de partículas que tengo por ahí a ver si se nota un cambio en el rendimiento.
Edito: Con arm-linux-g++ --version dice que es la 4.0.2, o sea que supongo que quiere decir que sí convierte a punto fijo!!!
el devkitgp2x lleva gcc 4.0 seguro.
lo q ocurre es q el -msoftfloat lo pone el compilador solo, no hace falta incluirlo. para saber si esto hace algo, habria q comparar con un gcc anterior o desactivar el -softfloat.
mejor compara a compilar sin cambiar nada y con las librerias estas q te ha propuesto archer... si estoy en lo cierto no habrá variacion en el rendimiento, y si estoy equivocado si habria diferencia...
salu2
el devkitgp2x lleva gcc 4.0 seguro.
lo q ocurre es q el -msoftfloat lo pone el compilador solo, no hace falta incluirlo. para saber si esto hace algo, habria q comparar con un gcc anterior o desactivar el -softfloat.
mejor compara a compilar sin cambiar nada y con las librerias estas q te ha propuesto archer... si estoy en lo cierto no habrá variacion en el rendimiento, y si estoy equivocado si habria diferencia...
salu2
Pues sí, parece que da lo mismo con el flag que sin él: he probado con el sistema de partículas y, teniendo en cuenta que pinta 9000 partículas y que las actualiza (un par de divisiones, un par de multiplicaciones y unas 10 sumas con floats por cada partícula) a algo menos de 25 FPS creo que se debería notar la diferencia. O sea que sí que debe estar incluído.
Bueno, si tengo tiempo ya probaré con las librerías de A.r.R.c.H.E.r., aunque por lo que veo tendré que cambiar bastante código.
Saludos.
hermes PS2R
02/01/2006, 21:01
..., pero no sé qué versión de gcc/g++ utiliza. Si escribo arm-linux-g++ --help no aparece la versión y no he encontrado ningún parámetro para saberlo.
Prueba a poner: arm-linux-g++ --version
Y te aparecera algo similar a esto ;)
arm-linux-g++.exe (GCC) 4.0.2
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Prueba a poner: arm-linux-g++ --version
Gracias Hermes. En el post #5 ya lo descubrí. :)
namikata
05/01/2006, 14:25
Hola buenas, mi primer post :)
En fin, soy uno de muchos que estan esperando para conseguir una 2x, y de mientras me he puesto a trastear un poco. Aviso, soy MUY novato (soy programador en windows con c#2.0 y managed directX y aqui me teneis programando en linux, con Python y SDL [wei5]
Finalizadas las presentaciones, al tema, estoy desarrollando un pequeño juego, de naves tambien, pero quien dice naves dice tomates asesinos o zombies, es como mezclar el quake3, con el asteroids :loco: (vista vertiical, DM1-1, DMEquipos y un sistema muy extraño de armas que todavia no acabo de comprender que habia tomado cuando lo escribi) , y despues de leer el hilo me preguntaba:
- alguien sabe como utilizar fixed point en Python? a lo mejor estoy preguntando una burrada pero llevo 2 dias con el lenguaje y es un poco nuevo para mi
- habeis probado algun ejemplo que os de idea del rendimiento de Python en la 2x? ya se que al ser interpretado ira mas lento pero mira que bien tiraba el Blade of Darkness y estaba hecho en Python.
- una vez que tenga el juego terminado en linux, solo tendria que copiarlo para que funcionase? (aparte de cambiar los controles)
Gracias!!! [wei4]
- alguien sabe como utilizar fixed point en Python? a lo mejor estoy preguntando una burrada pero llevo 2 dias con el lenguaje y es un poco nuevo para mi
- habeis probado algun ejemplo que os de idea del rendimiento de Python en la 2x? ya se que al ser interpretado ira mas lento pero mira que bien tiraba el Blade of Darkness y estaba hecho en Python.
- una vez que tenga el juego terminado en linux, solo tendria que copiarlo para que funcionase? (aparte de cambiar los controles)
Hola namikata.
Siento no poder ayudarte con Python, ya que lo usé hace un año para un proyecto muy sencillo pero luego lo olvidé. A ver si alguien te puede ayudar.
namikata
05/01/2006, 20:22
Gracias de todas formas, supongo que habra que esperar a que tenga una gp2x y hacer unas pruebas, es que despues de leer unos cuantos hilos en los que hablais de como estais programando los juegos me acojone un poco :rolleyes: y he tirado hacia algo mas sencillo
(es que venir de programar con una interfaz que lo hacia todo por ti, y encontrarse uno con esos makes que he visto en otros hilos...)
Ya que estamos, hay algun hilo / zona del foro en la que pueda comentar los detalles del juego con otra gente? es que es muy raro, de verdad, y me gustaria pedir consejo y tal, no sea que despues de programarlo, sea una caca xD
Namikata, mírate este PDF (http://www.arm.com/pdfs/DAI0033A_fixedpoint.pdf), referido al punto fijo. Igual puedes sacarle algo de provecho.
namikata
05/01/2006, 22:28
Gracias por el documento. Acabo de descubrir qu soy mas tonto de lo que pensaba xD
En fin, tendre que pedir sopitas para que me echen una mano, y sino, capaz de trabajar todo en intehgers xD
El documento esta muy bien gracias, pero en mi esta desaprovechado.
El documento esta muy bien gracias, pero en mi esta desaprovechado.
A mí me pasa lo mismo. Pero siempre estamos a tiempo de aprender. :)
anibarro
06/01/2006, 01:36
En un tutorial de un motor 3D que tenía por ahí, explicaban muy sencillito las bases del punto fijo, y entendiendo esto no tendréis problemas para entender el pdf ;) Lo pongo traducido como pueda al español:
Fixed point es una forma rápida de representar reales en un procesador que sólo soporta cálculos con enteros. Se trata de tomar un cierto número de bits como si fuese la parte decimal. Por ejemplo en la GP32 tenemos registros de 32 bits, asi que podriamos decir que para nosotros, los 16 primeros bits representan la parte entera y los 16 de menor peso la parte decimal.
Por tanto ejemplos de números decimales expresados según ese convenio serían:
1.0 = 00010000h ,1 por un lado(0001h), y 0 por otro(0000h)
1.5 = 00018000h ,1 por un lado(0001h), y 32768 por otro(8000h), que es la mitad +1 del maximo representable con 16bits. La parte decimal va de 0 a 0.99 en decimal y de 0 a FFFF en hexadecimal..., asi que 0.5 es la mitad de maximo numero representable (FFFF/2+1=8000), más uno teniendo en cuenta el 0.
Siguiendo tenemos:
0.25 = 00004000h
3.75 = 0003C000h
5.125 = 00052000h
El programador debe decidir cuántos bits dedicar al valor entero y cuantos a la precisión. Con 16 bits tenemos una precisión de 65534 valores, aproximadamente el número más pequeño representable distinto de 0 sería el 1/65534=0.0000152, una precisión suficiente para la mayoría de las tareas. Aunque dependiendo del rango que queramos siempre podemos trabajar con 24.8 o cualquier otra distribución.
A la hora de operar con esta representación de números decimales, la suma y la resta funcionan sin problemas, operando como si se tratase de un único numero entero de 32 bits, y luego volviéndolo a interpretar en coma fija:
1.5 + 1.5 = 3.0 00018000h + 00018000h = 00030000h
2.75 - 2.25 = 0.5 0002C000h - 00024000h = 00008000h
Para multiplicar y dividir tendremos que hacer algunos ajustes antes de operar.
Después de una multiplicación, debemos dividir el resultado por la precisión elegida. Si tenemos 16bits de precisión debemos hacer lo siguiente:
1.5 * 3.0 = 4.5 00018000h * 00030000h = 000480000000h (incorrecto)
Debemos dividir por 10000h=2^16 (16 bits precision):
00018000h * 00030000h = 000480000000h / 10000h = 00048000h (correcto)
Al revés que en la multiplicación, en la división debemos multiplicar para corregir los factores ANTES de realizar la división, si no perderemos decimales en cada operación:
7.5 / 2.5 = 3.0 00078000h / 00028000h = 0003h (incorrecto)
Necesitamos multiplicar antes por la precisión:
00078000h * 00010000h = 000780000000h / 00028000h = 00030000h (correcto)
Vemos que en la multiplicación, antes de hacer las correciones, obtenemos un número de más de 32 bits y en la división, al hacer la correción nos pasa lo mismo, por lo que las variables que usen este sistema de punto fijo deberán de estar declaradas como "long" de 64bits y no simplemente int de 32 bits. En caso de querer implementarlo en ensamblador, pues tener esto en cuenta.
El Original:
Fixed point is an easy way to represent non-integer numbers with only
integers in the processor. It's done by taking a certain number of bits in
a register, and dedicating them to decimal places instead of integer
values. Like if we have a 16-bit word, we can do 8.8 fixed point by using
the upper 8 bits as the "whole" portion of the number, and the lower 8 bits
as the "fractional" portion.
Examples of 8.8 fixed point....
1.0 = 0100h
1.5 = 0180h
0.25 = 0040h
3.75 = 03C0h
5.125 = 0520h
...and so on. All we're doing is using the high byte as the whole, and the
low byte as the precision. How precise? Well since we have 8 bits in the
fraction, it means we can go down to 1/256 for a fractional value. The more
the fractional bits you use, the more accurate your decimal places can
be... but the fewer number of whole-number bits you have left (so your
value can't go up as high).
Sure enough, you're not limited to equal splits. With 16 bits you can do
things like 15.1 fixed point (which only goes down to 0.5 for decimal units
but allows numbers up to 32767), or you can do 1.15, which can only have a
whole number of 0 or 1, but goes down to 1/32768 of decimal accuracy. You
choose what works well for your system.
(Incidentally, since I code 32-bit mostly these days, I use 16.16 fixed
point for pretty much everything 3D-wise. It's accurate enough in decimal
places, yet has wholes up to 64k which is a nice range).
To sum up, fixed point is just treating integers as fractional numbers by
working with the numbers a few powers of 2 above what the number actually
means. In 8.8, 0100h (256) means 1, 512 means 2, 768 means 3, etc...
you're just scaling the operations up a bit so you can stick with integer
operations.
Adding and subtracting fixed point is just like regular integer add and
sub. You don't have to do anything special...
1.5 + 1.5 = 3.0 0180h + 0180h = 0300h
2.75 - 2.25 = 0.5 02C0h - 0240h = 0080h
...and so on. On the other hand, multiplication and division have to be
adjusted by the number of places in your precision, since the resulting
number would be too high for multiply, and too low for divide....
1.5 * 3.0 = 4.5 0180h * 0300h = 048000h
NOPE! We have to divide by 100h (8 bits precision).
0180h * 0300h = 048000h / 100h = 0480h (correct)
Likewise, division needs to get multiplied by your precision. This must be
done BEFORE you divide, or you'll end up losing all your decimal places.
7.5 / 2.5 = 3.0 0780h / 0280h = 0003h
WRONG! We need to multiply....
0780h * 0100h = 078000h / 0280h = 0300h (correct)
Note that this means for multiply and divide that you'll need more space
than just what's in your fixed point registers. Luckily multiply and
divide on the Intel processors multiply into and from EDX:EAX, so you've
got extra space already even if you're using assembly language. And the
adjustment mul/divs are all powers of two, so you can use bit shifts
instead (if you are using 386 regs, make sure you look up the SHLD and SHRD
instructions... they come in real useful for this...)
¡Ualaaa! ¡Qué currada, Anibarro! Muchísimas gracias. Me lo leo en cuanto pueda.
namikata
06/01/2006, 03:30
Ahora si que me he enterado bien de como funciona.
, y al releer el pdf lo entiendo mejor. Todavia estoy terminando el diseño pero en cuanto empiece con el codigo me hare unas pequeñas funciones para trabajar con ellas.
Veremos que tal se me da a la hora de la verdad xD
Muchas gracias!!!
anibarro
06/01/2006, 05:14
jje no hay de que, ahora faltan el resto de operaciones xD
He probado a compilar una cosa que estoy haciendo y con -msoftfloat no hay ninguna diferencia como se decía antes. En cambio con la math-sll he incrementado la velocidad en 2-3 fps (aun no lo he implementado por todo el código).
La verdad es que está bastante bien y no lleva mucho tiempo meterla :)
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.