Page 1 sur 3

INT : Fonction trop lente

Publié : mar. 26/mai/2009 19:27
par Le Soldat Inconnu
Salut,

voilà un simple comparatif de vitesse qui est à mon avis assez évoquant

D'un coté : INT
De l'autre : Un code tout simple 16 fois plus rapide que INT chez moi, simplement mettre le float - 0.5 dans un long

le test

Code : Tout sélectionner

Float1.f = 5.958741545
Float2.f = 6.12154872534

#Nb = 50000000

Time1 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long11.l = Int(Float1)
  Long12.l = Int(Float2)
Next
Time2 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long21.l = Float1 - 0.5
  Long22.l = Float2 - 0.5
Next
Time3 = ElapsedMilliseconds()

Texte.s = "Int :" + Chr(10) + "Time = " + Str(Time2 - Time1) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long11) + Chr(10) + StrF(Float2) + " -> " + StrF(Long12) + Chr(10) + Chr(10) + "Float - 0.5 to Long :" + Chr(10) + "Time = " + Str(Time3 - Time2) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long21) + Chr(10) + StrF(Float2) + " -> " + StrF(Long22) + Chr(10) + StrF((Time2 - Time1) / (Time3 - Time2), 1) + " time more fast"
SetClipboardText(Texte)
MessageRequester("Test", Texte)
résultat
Int :
Time = 2235 ms
5.958742 -> 5.000000
7.125487 -> 7.000000

Float - 0.5 to Long :
Time = 140 ms
5.958742 -> 5.000000
7.125487 -> 7.000000
16.0 time more fast
et chez vous ?

Publié : mar. 26/mai/2009 19:39
par Atomo
J'obtient ce résultat avec le débugger off :
Int :
Time = 686 ms
5.958742 -> 5.000000
6.121549 -> 6.000000

Float - 0.5 to Long :
Time = 110 ms
5.958742 -> 5.000000
6.121549 -> 6.000000
6.2 time more fast

Publié : mer. 27/mai/2009 7:59
par kelebrindae
---------------------------
Test
---------------------------
Int :
Time = 3859 ms
5.958742 -> 5.000000
6.121549 -> 6.000000

Float - 0.5 to Long :
Time = 203 ms
5.958742 -> 5.000000
6.121549 -> 6.000000
19.0 time more fast

Impressionnant ! 8O

Une question (bête, sans doute): à quoi sert le "-0.5" ?

Publié : mer. 27/mai/2009 8:37
par cha0s
sous mon nux :
Int :
Time = 4259 ms
5.958742 -> 5.000000
6.121549 -> 6.000000

Float - 0.5 to Long :
Time = 324 ms
5.958742 -> 5.000000
6.121549 -> 6.000000
13.1 time more fast

Publié : mer. 27/mai/2009 9:05
par Good07
Sur mon IMac intel core 2 duo 2,4 ghz 2 GO de ram
Pure Basic 4.31 Béta 1

Avec debogueur en service:
Int :
Time = 8604 ms
5.958742 -> 5.000000
6.121549 -> 6.000000

Float - 0.5 to Long :
Time = 7628 ms
5.958742 -> 5.000000
6.121549 -> 6.000000
1.1 time more fast
Sans debogueur:

Int :
Time = 316 ms
5.958742 -> 5.000000
6.121549 -> 6.000000

Float - 0.5 to Long :
Time = 145 ms
5.958742 -> 5.000000
6.121549 -> 6.000000
2.2 time more fast
Il semble que le debogueur patauge dans la choucroute... 8O

Publié : mer. 27/mai/2009 10:05
par Le Soldat Inconnu
ma première solution n'est pas la meilleure, elle ne marche pas à tous les coups

voici une version meilleure, qui reste 2 fois plus rapide

Code : Tout sélectionner

Procedure MyInt(Float.f)
  Protected Long.l
  Long = Float
  If Float > 0
    If Float < Long
      Long - 1
    EndIf
  Else
    If Float > Long
      Long + 1
    EndIf
  EndIf
  ProcedureReturn Long
EndProcedure

Float1.f = 5.958741545
Float2.f = 5

#Nb = 50000000

Time1 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long11.l = Int(Float1)
  Long12.l = Int(Float2)
Next
Time2 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long21.l = MyInt(Float1)
  Long22.l = MyInt(Float2)
Next
Time3 = ElapsedMilliseconds()

Texte.s = "Int :" + Chr(10) + "Time = " + Str(Time2 - Time1) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long11) + Chr(10) + StrF(Float2) + " -> " + StrF(Long12) + Chr(10) + Chr(10) + "Float - 0.5 to Long :" + Chr(10) + "Time = " + Str(Time3 - Time2) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long21) + Chr(10) + StrF(Float2) + " -> " + StrF(Long22) + Chr(10) + StrF((Time2 - Time1) / (Time3 - Time2), 1) + " time more fast"
SetClipboardText(Texte)
MessageRequester("Test", Texte)

Publié : mer. 27/mai/2009 10:53
par lionel_om
Le truc de ton code d'avant c'est que y'avait pas d'appel à une fonction. Donc pas d'utilisation de la pile, etc...

Essaye juste ça: (même code que toi, mais le calcul est fait dans une fonction).

Code : Tout sélectionner

Float1.f = 5.958741545
Float2.f = 6.12154872534

#Nb = 50000000

Procedure.l Test(Float.f)
  ProcedureReturn Float - 0.5
EndProcedure


Time1 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long11.l = Int(Float1)
  Long12.l = Int(Float2)
Next
Time2 = ElapsedMilliseconds()
For i = 1 To #Nb
  Long21.l = Test(Float1)
  Long22.l = Test(Float2)
Next
Time3 = ElapsedMilliseconds()

Texte.s = "Int :" + Chr(10) + "Time = " + Str(Time2 - Time1) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long11) + Chr(10) + StrF(Float2) + " -> " + StrF(Long12) + Chr(10) + Chr(10) + "Float - 0.5 to Long :" + Chr(10) + "Time = " + Str(Time3 - Time2) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long21) + Chr(10) + StrF(Float2) + " -> " + StrF(Long22) + Chr(10) + StrF((Time2 - Time1) / (Time3 - Time2), 1) + " time more fast"
SetClipboardText(Texte)
MessageRequester("Test", Texte)
Pour moi la fonction n'est plus que 4 fois plus rapide. Pas mal toujours, mais beaucoup moins impressionnant !!!

/Lio

Publié : mer. 27/mai/2009 13:11
par erix14
Pourquoi tu n'utilise pas la fonction ASM fistp ?

Code : Tout sélectionner

Procedure IntASM(f.f)
	Protected i.i
	FLD f
	fistp i
	ProcedureReturn i
EndProcedure

Publié : mer. 27/mai/2009 13:54
par cha0s
Intéressant :

Code : Tout sélectionner

Procedure IntASM(f.f)
  Protected i.i
  EnableASM
  FLD f
  FISTP i
  DisableASM
  ProcedureReturn i
EndProcedure


Float1.f = 5.958741545
Float2.f = 5
#Nb = 50000000
Time1 = ElapsedMilliseconds()

For i = 1 To #Nb
 Long11.l = Int(Float1)
 Long12.l = Int(Float2)
Next

Time2 = ElapsedMilliseconds()

For i = 1 To #Nb
 Long21.l = IntASM(Float1)
 Long22.l = IntASM(Float2)
Next

Time3 = ElapsedMilliseconds()

Texte.s = "Int :" + Chr(10) + "Time = " + Str(Time2 - Time1) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long11) + Chr(10) + StrF(Float2) + " -> " + StrF(Long12) + Chr(10) + Chr(10) + "IntASM :" + Chr(10) + "Time = " + Str(Time3 - Time2) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long21) + Chr(10) + StrF(Float2) + " -> " + StrF(Long22) + Chr(10) + StrF((Time2 - Time1) / (Time3 - Time2), 1) + " time more fast"
SetClipboardText(Texte)
MessageRequester("Test", Texte)
Int :
Time = 3826 ms
5.958742 -> 5.000000
5.000000 -> 5.000000

Float - 0.5 to Long :
Time = 604 ms
5.958742 -> 6.000000
5.000000 -> 5.000000
6.3 time more fast

Publié : mer. 27/mai/2009 14:20
par erix14
Et avec une macro, c'est encore plus rapide :wink:

Code : Tout sélectionner

Macro FloatToInt(float,long)
	FLD float
	FISTP long
EndMacro

Float1.f = 5.958741545
Float2.f = 5
#Nb = 50000000
Time1 = ElapsedMilliseconds()

For i = 1 To #Nb
	Long11.l = Int(Float1)
	Long12.l = Int(Float2)
Next

Time2 = ElapsedMilliseconds()

For i = 1 To #Nb
	Long21.l
	FloatToInt(Float1,Long21)
	Long22.l
	FloatToInt(Float2,Long22)
Next

Time3 = ElapsedMilliseconds()

Texte.s = "Int :" + Chr(10) + "Time = " + Str(Time2 - Time1) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long11) + Chr(10) + StrF(Float2) + " -> " + StrF(Long12) + Chr(10) + Chr(10) + "IntASM :" + Chr(10) + "Time = " + Str(Time3 - Time2) + " ms" + Chr(10) + StrF(Float1) + " -> " + StrF(Long21) + Chr(10) + StrF(Float2) + " -> " + StrF(Long22) + Chr(10) + StrF((Time2 - Time1) / (Time3 - Time2), 1) + " time more fast"
SetClipboardText(Texte)
MessageRequester("Test", Texte)

Publié : mer. 27/mai/2009 15:02
par lionel_om
erix14 a écrit :Et avec une macro, c'est encore plus rapide :wink:
Normal: dans tous les cas une macro sera plus rapide qu'une fonction...
/Lio :wink:

Publié : mer. 27/mai/2009 15:11
par erix14
@lionel_om : Bien sûr, c'est une évidence... dans cet exemple, une macro est plus qu'indiqué, car le code est très petit et le CPU passe plus de temps sur l'appel de la procédure que sur le contenu de la procédure. :wink:

Publié : mer. 27/mai/2009 16:52
par Fig
Question: Mais qu'est ce qui a bien pu être mis dans cette fonction int() nativement pour qu'elle soit si lente (?!!) 8O

Publié : mer. 27/mai/2009 18:27
par Backup
erix14 a écrit :@lionel_om : Bien sûr, c'est une évidence... dans cet exemple, une macro est plus qu'indiqué, car le code est très petit et le CPU passe plus de temps sur l'appel de la procédure que sur le contenu de la procédure. :wink:
oui mais dans la mesure ou pour le purebasic, il s'agit bien d'une fonction 'int()'
je crois que de le faire en fonction est plus judicieux !!

le but final serai de remplacer celle existante :)

Publié : mer. 27/mai/2009 18:37
par djes
Fred a répondu dans le forum anglais.
Well int() is function, so you have a call function penality. And in the VC8 float->int conversion, it calls ftol2() which is another call. No wonder why it's slower. May be it could be optimized by inlining the function in the compiler, but it's optimization, not a bug.
Autrement dit, Int() est une fonction qu'a repris Fred du compilateur utilisé par la plupart des programmes créés sous Windows, y compris Purebasic (VC8, ça a été une révision majeure de PB il y a quelques temps). A mon avis Fred ne l'a pas inventé, comme beaucoup d'autres fonctions, d'autres s'y sont déjà employé qui ont pris en compte tout un tas de paramètres auxquels nous ne pensons même pas (rétro compatibilité, multi processeurs). Tout ça, ça implique des tas de conditions qui ralentissent forcément l'exécution d'une fonction. Or, dans le cas de quelque chose d'essentiel comme int(), c'est dommageable. C'est d'ailleurs ce genre de truc qui fait que windows est de plus en plus lent!
Fred pourrait effectivement créer une fonction optimisée, mais ce serait à ses risques et périls, et ce, pour toutes les fonctions bas niveau comme celle-là. Il le fait parfois :)