Recherche de performances

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 2 sept. 2005 à 19:04
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 - 4 sept. 2005 à 22:09
Violent Ken

Salut. Je suis en train de faire un algorithme de calcul, et j'aimerais l'optimiser au maximum.
Par exemple, est-il plus rapide de faire

for x=1 to 10
a=a+30
next x

ou

for x=1 to 30
a=a+10
next x

est-il plus rapide de faire

if a=1 then
else
end if

ou d'utiliser Iif

est-il plus rapide de faire

While a < 500
a = a + 1
Wend

ou

Do Until a = 500
a = a + 1
Loop

a=b^0.5 ou a=sqr(b)

Il y a des tas de possibilités pour faire une même action, et j'aimerais que vous me donniez des astuces pour pouvoir 'optimiser' au maximum le code.
Merci, @+

Note: je sais que le C est bien plus rapide que le VB, mais je compte faire mon algo en VB

33 réponses

cs_CanisLupus Messages postés 3757 Date d'inscription mardi 23 septembre 2003 Statut Membre Dernière intervention 13 mars 2006 21
3 sept. 2005 à 18:13
Pour le DoEvents, j'ai seulement dit "...est souvent nécessaire...", je n'ai pas dit indispensable. Et je rejoins us_30 et violent_ken sur ce point.

De toutes façons, tout dépend de ce qu'on veux faire. Comme on dit, on ne peux avoir le beurre ET l'argent du beurre (certains rajouteraient : ET le ... de la crémière).

Si on veut faire quelque chose de TRES performant on choisit le C ou l'ASM et si on n'a que VB, on suit les conseils que BruNews donne dans ces posts sur ce topic.

Dans tous les cas, il faut transiger, voir au cas par cas, surtout quand il s'agit d'applis avec interface utilisateur (dans ce cas, il faut même avoir des notions de psycho). Un utilisateur final se fout de savoir qu'une boucle met 1 ou 1000 millisecondes, ce qu'il voit c'est le résultat.
Il est bien évident, qu'en tant que programmeur, il faut se préoccuper de la perf de son code mais aussi de la perf apparente à l'utilisateur en terme d'ergonomie et de liberté.
Mettre un DoEvents dans une boucle qui ne mobilise pas trop de ressources, c'est bête.
Ne pas le mettre dans une boucle qui risque de mobiliser toutes les ressources du PC pendant 1/2 heure, c'est suicidaire. Même si on a prévenu l'utisateur (il peut vouloir lire ses mails ou jouer au solitaire en attendant ?).

En dehors du DoEvents, il y a aussi d'autres astuces qui n'ont (apparemment) rien à voir avec la prog pure. Comme placer certains traitements longs là ou l'utilisateur s'attend à ne pas recevoir une réponse immédiate....

-------------------------------------------------
Dresseur de puces, .... normal pour un loup !?
0
us_30 Messages postés 2065 Date d'inscription lundi 11 avril 2005 Statut Membre Dernière intervention 14 mars 2016 10
3 sept. 2005 à 23:38
Bon Okay pour DoEvents, passons un peu à autre chose...

PCPT, Pour le Prog de test, je ne disais pas du mal... loin de moi cette idée... mais effectivement, perso, je pense qu'il faudrait bien prendre en compte le temps d'appel pour le déduire... C'est qu'une simple question de math pour la comparaison. Si deux procédures rapides sont trés proches l'une de l'autre, avec un temps d'appel non négligeable (proportionnellement), la comparaison deviendra nécessairement ardue ! ...

Autre chose. Dans les énumérations qu'on peut voir dans les tutos, je crois qu'il n'y a pas celle-ci. Pour le calcul des puissances au carré, il est beaucoup plus rapide de faire X*X que X^2 ... En fait, c'est même plus compliqué que cela... LES calculs X^3, X^4, etc... donnent un temps quasi-constant, qu'alors X*X*...*X augmentent avec le nb de X... En non compilé, les temps d'exécution s'équilibrent pour environ X^9... curieux non ? ... et bon à savoir...

Encore autre chose. Question peut-être bête, mais bon... existe-t-il un autre compilateur d'un listing VB meilleur que celui de Microsoft ? ... en évitant du code stupide comme le soulignait hier Brunews...

Amicalement,
Us.
0
us_30 Messages postés 2065 Date d'inscription lundi 11 avril 2005 Statut Membre Dernière intervention 14 mars 2016 10
4 sept. 2005 à 13:36
Voici une optimisation que je viens de trouver en remplacement de IF t mod 90=0 then ... c.a.d. exécuter un sous programme une fois tous les X fois... comme on en parlait...

LISTING 1 : Celui de base :

Sub essai()
temps = Timer
Dim t As Long
Dim a As Long
Dim b As Long
Dim bm As Long
bm = 10000000
For t = 0 To bm
If t Mod 90 0 Then a a + 1 'SP1
b = b + 1 'SP2
Next t
MsgBox Timer - temps & " " & a & " " & b
End Sub


LISTING 2 : L'optimisation qui réalise exactement la même chose :

Sub essai2()
temps = Timer
Dim t As Long
Dim a As Long
Dim b As Long
Dim bf1 As Long
Dim bf2 As Long
Dim j As Long
Dim bm As Long
bm = 10000000
bf1 = bm \ 90 - 1
For j = 0 To bf1
a = a + 1 'SP1
bf2 = j * 90 + 90 - 1
For t = j * 90 To bf2
b = b + 1 'SP2
Next t
Next j
a = a + 1 'SP1
For t = j * 90 To bm
b = b + 1 'SP2
Next t
MsgBox Timer - temps & " " & a & " " & b
End Sub


L'avantage du second est de plus en plus nette, dès le saut (ici 90) est important... En fait pour un saut de 2 fois, c'est le LISTING 1 le plus rapide, au delà c'est le second... Ici, pour 90, le LISTING 2 est environ 2,5 fois plus rapide que le premier...

Comme j'utilise cette structure dans qlq'uns de mes algos, j'ai déjà une optimisation conséquente...

Voilà, comme quoi, on va tarir le sujet tout de suite...

Amicalement,
Us.
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
4 sept. 2005 à 19:43
Violent Ken

PCPT a dit "umm, j'aurais supposé que mon timer aurait bien servi et remué les foules....
(à tord apparemment....)"
Bah à minuit je dormais, et ce week end j'étais pas là...
Mais je ne manquerait pas de l'essayer, promis !

Quand au Doevents, le mettre à toutes les boucles sans utiliser un truc du style" if (a mod x)", c'est du suicide pur pour les performances du programme : une simple boucle

For x = 1 To 5000000
DoEvents
a = a + 1
Next

mettra 8 secondes sur mon PC

et
For x = 1 To 5000000
a = a + 1
Next
mettra 0.5 secondes....

Le doevents divise la vitesse par 16!!

Un nouvel essai avec la command Mod

Private Sub Form_Load()
For x = 1 To 5000000
If (x Mod 10000) = 0 Then DoEvents
a = a + 1
Next
End Sub

mettra environ 2 secondes....
Alors faut mieux envisager le doevents avec le mod, et doser la valeur 10000 en fonction du processeur, pour rendre la main de tps en tps en perdant le moins de vitesse possible.

Bon, grâce à PCPT je vais pouvoir tester mes algorithmes, et je jetterai aussi un oeil sur les sources de us_30 pour les nombres premiers....

En tout cas merci à tous, c'est sympa de m'aider !
@+
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 sept. 2005 à 20:17
En fait on ne peut pas prédire vraiment le ralentissement du à DoEvents.
On passe à la ligne qui suit DoEvents SEULEMENT quand PeekMessage ne trouvera plus rien sur la pile d'appels du thread.

while PeekMessage
TranslateMessage
DispatchMessage
wend

Il est clair que ceci peut être une cata pour un calcul, le moindre clic souris nimporte où sur la fenêtre génère une rafale de messages, ne parlons pas de mouvement ou repaint, là c'est la misère totale.

C'est à ce genre de trucs qu'on comprend qu'il était plus que temps de changer ce langage, même si le passage à vb.net n'est pas toujours évident.

ciao...
BruNews, MVP VC++
0
us_30 Messages postés 2065 Date d'inscription lundi 11 avril 2005 Statut Membre Dernière intervention 14 mars 2016 10
4 sept. 2005 à 20:42
Bonsoir,

Juste une précision, je ne parlais pas de nombre premier ! -:); mais c'est sans importance... Bon, aller, j'arrête pour le moment de discuter sur les optimisations... intéressant du reste...

Amicalement,
Us.
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
4 sept. 2005 à 20:49
Violent Ken

Us_30, j'ai parlé de nombres premiers car à l'origine, mon problème était d'optimiser ma source de calcul de nombres premiers. Je suis donc allé jeter un coup d'oeil sur tes sources pour voir tes déclaration des variables, l'utilisations des boucles (for/next ou while/wend)... pour pouvoir comparer à ce que j'avais fait !

Et BruNews, quoi qu'on en dise sur les doevents, il est possible (dans une certaine mesure) de prédire le ralentissement du à cette commande; j'ai fait une expérience :

for y=1 to 50000000
a=a+1
if (y mod X)=0 then doevents
next

J'ai fait plusieurs mesures du temps mis pour éxecuter cette boucle en fonction de X.
Et bien le temps d'exécution décroit de manière exponentielle quand X augmente, et on remarque que pour X>40, le temps ne décroit plus bcp. C'est donc cette valeur , X=40, que l'on conservera dans ce cas, puisqu'elle permet une vitesse quasi-maximum en rendant la main assez souvent.


@+
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
4 sept. 2005 à 21:00
Violent_Ken, pour info avec tes valeurs (test unique) :


For x 1 To 5000000: DoEvents: a a + 1: Next
IDE : 16299,5548 ms
EXE : 15451,6381 ms


For x 1 To 5000000: a a + 1: Next
IDE : 523,3333 ms
EXE : 15,895 ms


For x 1 To 5000000: a a + 1: If (x Mod 10000) = 0 Then DoEvents: Next
IDE : 1427,7784 ms
EXE : 265,2508 ms



peut-être qu'on mélange un peu le temps de calcul par rapport aux ressources qu'il demande.
perso, pour des calculs, c'est la vitesse dont j'ai besoin. là je place également un DoEvents avec un Mod .. selon mes besoins. par contre, dès que le graphique y est lié (exemple, déplacement de boutons), là le DoEvents est systématique, même sur une boucle de 40.



pour le dernier exemple (boucle avec Mod), elle demandera un calcul de plus à chaque ligne ; ce n'est qu'une question de compromis.

ps : pour X=40, ce n'est que parce que plus il y a de calculs et plus le proc met de temps à les faire, jusqu'à ce qu'il atteigne son "seuil minimal" (si on peut dire)
sachant tout de même que ce X sera variable selon chaque PC


++
PCPT
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
4 sept. 2005 à 21:09
Violent Ken

Je suis pas sur d'avoir bien compris ta remarque, pcpt (ou peut-être que c'est toi qui a pas bien compris la mienne, je ne sais pas)
Je disais juste que pour un programme de calcul, où l'on recherche des performances, mettre un simple "doevents" est catastophique, le tps d'exécution est énorme.
J'ai donc cherché a mettre un
if (y mod UneValeur)=0 then Doevents
pour faire un doevents de tps en tps, histoire que le programme ne perde pas totalement la main.
J'ai donc cherché à modifier la valeur UneValeur pour voir les différences de tps mises par mon PC pour effectuer la boucle.
Résulats : Le temps d'exécution décroit de façon exponentielle quand UneValeur augmente, mais comme toute fonction exponentielle décroissante, elle atteint une limite, et le tps d'exécution ne décroit guère plus pour UneValeur>40. J'en ai donc déduit que cette valeur de 40 est la bonne pour mon programme, puisque c'est elle qui me permet d'avoir une vitesse rapide tout en randant la main assez souvent.
C'est peut-être plus clair comme, cà.
@+
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 sept. 2005 à 21:15
le calcul modulo dans la boucle ne consomm-t-il pas énormément ?
Par contre l'idée est bonne mais faut se débarasser de la division interne au modulo.

On peut prendre la valeur la plus proche de 10000 ayant tous ses bits bas à 1, ce qui donne 8191.

qlq'un pourait-il retester la même boucle en remplaçant par:
If x And 8191 Then DoEvents
au lieu de: If (x Mod 10000) = 0 Then DoEvents

ciao...
BruNews, MVP VC++
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
4 sept. 2005 à 21:32
Violent_ken -> j'avais bien compris ^^
BruNews -> oui, le Mod comsomme beaucoup, c'est pour çà que je précisais à Ken la différence entre la consommation et le temps d'execution. avec ce Mod, la boucle consommera +, mais sera + rapide. d'ou le fait du compromis entre la vitesse d'execution et les ressources que l'on veut fixer à certaines procédures....
For x 1 To 5000000: a a + 1: If (x And 8191) Then DoEvents: Next
IDE : 24370,9469
ms
EXE : 13858,3949 ms

PCPT
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 sept. 2005 à 21:51
OUPS, ben je ne suis vraiment plus habitué au vb, me suis gourré grave:
If (x And 8191) = 0 Then DoEvents

pas étonnant que les temps étaient si mauvais.

ciao...
BruNews, MVP VC++
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
4 sept. 2005 à 22:09
IDE : 1431,0752ms
EXE : 37,3134ms
610 DoEvents
donc la solution la plus rapide.

nb : 500 DoEvents avec le Mod 10000.
le choix est vite fait. je garde çà sous le coude. EXTRA !
PCPT
0
Rejoignez-nous