begin process at 2012 05 27 14:53:40
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > CONVERSION FLOAT -> INT

CONVERSION FLOAT -> INT


 Information sur la source

 Description

Pendant que j'écrivais un prog qui faisanit pas mal de conversion float vers int, j'ai regardé le code assembleur généré et je me suis aperçu que le prog passait son temps à modifier le registre de contrôle du FPU avant de faire sa conversion et perdait ainsi tu temps.

j'ai voulu vois ce que j'obtenai en faisant moi-même la conversion :
un float est représenté sous 32 bits comme ceci :
signe*1.m * 2^exp

bit 31 : signe.
bits 30..23 : exposant+127.
bits 22..0 : partie fractionnaire de la mantisse.


Source

  • #include <windows.h>
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <conio.h>
  • //******************************************************************
  • //******************************************************************
  • int ftoi(float f)
  • {
  • DWORD dw = *((DWORD*) &f);
  • if(dw == 0)
  • return 0;
  • char exp = (char) (((dw>>23)&0xFF)-127);
  • if(exp < 0 || exp > 23)
  • return 0;
  • int val = (1<<exp) + ((dw&0x7FFFFF)>>(23-exp));
  • if(dw&0x80000000)
  • return -val;
  • else
  • return val;
  • }
  • #define NB_BCL 100000000
  • float floatVal;
  • int intVal;
  • //******************************************************************
  • //******************************************************************
  • int main()
  • {
  • srand(GetTickCount()^GetCurrentProcessId());
  • DWORD dwDeb1 = GetTickCount();
  • for(int i = 0; i < NB_BCL; i++)
  • {
  • int val = rand();
  • floatVal = val/3.14159f;
  • intVal = (int) (float)floatVal;
  • }
  • DWORD dwFin1 = GetTickCount();
  • DWORD dwDeb2 = GetTickCount();
  • for(int j = 0; j < NB_BCL; j++)
  • {
  • int val = rand();
  • floatVal = val/3.14159f;
  • intVal = ftoi(floatVal);
  • }
  • DWORD dwFin2 = GetTickCount();
  • printf("%d\r\n", dwFin1-dwDeb1);
  • printf("%d\r\n", dwFin2-dwDeb2);
  • system("PAUSE");
  • return 0;
  • }
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>


//******************************************************************
//******************************************************************
int ftoi(float f)
{
	DWORD dw = *((DWORD*) &f);
	if(dw == 0)
		return 0;

	char exp = (char) (((dw>>23)&0xFF)-127);
	if(exp < 0 || exp > 23)
		return 0;
	
	int val = (1<<exp) + ((dw&0x7FFFFF)>>(23-exp));
	if(dw&0x80000000)
		return -val;
	else
		return val;
}


#define NB_BCL	100000000

float floatVal;
int intVal;

//******************************************************************
//******************************************************************
int main()
{
	srand(GetTickCount()^GetCurrentProcessId());


	DWORD dwDeb1 = GetTickCount();
	for(int i = 0; i < NB_BCL; i++)
	{
		int val = rand();
		floatVal = val/3.14159f;
		intVal = (int) (float)floatVal;
	}
	DWORD dwFin1 = GetTickCount();

	DWORD dwDeb2 = GetTickCount();
	for(int j = 0; j < NB_BCL; j++)
	{
		int val = rand();
		floatVal = val/3.14159f;
		intVal = ftoi(floatVal);
	}
	DWORD dwFin2 = GetTickCount();

	printf("%d\r\n", dwFin1-dwDeb1);
	printf("%d\r\n", dwFin2-dwDeb2);

	system("PAUSE");
	return 0;
}

 Conclusion

résultat (celeron 800MHz):
conversion brute : 12s
avec ftoi : 6s
avec ftoi inline : 4s



 Sources du même auteur

Source avec Zip Source avec une capture SPLITTER API WIN32
Source avec Zip Source avec une capture UTILISATION DE LA LIB SHLWAPI.DLL (FONCTIONS DIVERSES SUR LE...
Source avec Zip Source avec une capture WIN32ACTIVEX : CONTENEUR DE CONTRÔLES ACTIVEX EN WIN32 (API ...
Source avec Zip Source avec une capture UTILISATION SPLITTER AVEC MFC
Source avec Zip Source avec une capture EXTRACTION DES ICONES DES EXÉCUTABLES (.EXE, .DLL), (VC++, W...

 Sources de la même categorie

Source avec Zip SCHEDULER RR FIFO par yvesB87
Source avec Zip ALGORITHMES RÉCURSIFS VS ALGORITHMES ITÉRATIFS par yvesB87
Source avec Zip Source avec une capture C++ FORMAT D'IMAGE AVEC QT par pop70
Source avec une capture EXEMPLE DE POINTEURS DE FONCTION par pop70
Source avec Zip Source avec une capture [C++] CLASS REGISTER par Miwik

Commentaires et avis

Commentaire de BruNews le 20/02/2004 20:22:29 administrateur CS

Salut,

http://www.movsd.com/
tu pourras y prendre MASM32 et dans son dossier Help se trouve Agner.hlp qui detaille tout cela et plus encore.

Exemple a suivre dans tous les cas, ne pas craindre d'aller voir ce que produit le compilo et tenter de faire mieux ne peut pas nuire.

ciao...

Commentaire de ccarniel le 20/02/2004 22:15:47

Si je prends ton code tel quel, j'obtiens les temps suivants:
4356 en calcul flottant
4166 en passant par ta routine ftoi
donc ta fonction semble mieux que ce qui est prévu par le compilateur.
Ma config est un Athlon XP1700+, mais peu importe.

Toutefois, si je modifie les paramètres du projet et que je lui permet d'utiliser le jeu d'instruction PIII et surtout les instructions SSE (présentes sur les Athlon XP), alors j'obtiens:
3155 en calcul flottant
4336 en passant par ta routine ftoi

Ce que je veux dire par là, c'est que l'optimisation du code n'était que dans ta routine C, le compilateur n'avait pas le droit d'utiliser tout son potentiel d'optimisation (pour pouvoir tourner sur 386 par exemple, c'est nécessaire).

A l'avenir si tu cibles des machines récentes dans tes programmes regarde aussi du coté des paramètres du projet, il y a aussi des choses à optimiser là :)

En tous cas, la démarche est bonne, il faut toujours être curieux.





Commentaire de ymca2003 le 20/02/2004 23:16:48

ccarniel : j'ai juste une petite question, ton processeur il tourne à 1700 MHz?
si oui comment ça se fait qu'avec la fonction ftoi il n'est pas plus rapide que ça?

j'ai essayé en modifiant les paramètres du projet sur le type de processeur et ça change que dal (au passage les essais sont en mode Release avec VC 6.0)

Commentaire de ccarniel le 20/02/2004 23:24:58

non un XP1700+ tourne à 1466MHz.
Sinon les ratio par rapport au Celeron 800 ne me choquent pas plus que ça.

J'ai utilisé Studio.Net pour changer mes paramètres, celui qui dépote vraiment c'est celui qui active SSE, bien plus que le type de processeur.
Ca se trouve sous C/C++ (Code Generation) : Enable Enhanced Instruction Set. Là, j'ai activé SSE.
Je ne sais pas si c'était déjà dispo sous VC++ 6.

Voili, voilou, bonne nuit, je vais me coucher :)

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,374 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales