Observez bien les 2 fonctions ci-dessous : elles sont identiques, sauf les 2 lignes en rouge qui ne sont pas au même endroit. J'ai laisser volontairement "le gras" autour car certains y trouver peut-être (j'espère !) une réponse à mes interrogations.
(Pour les amateurs d'imagerie il s'agit de la méthode de seuillage dite de Kohler)
fonction 1 :
fonction 2 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 unsigned char s; int i,j,k,n,m,p,q; unsigned char voisinage[4]; unsigned char pixel; double card, contraste; double Cmoy=0.0; unsigned char so=0; for (s=s_min; s<=s_max; s++) { contraste=0.0; card=0.0; for (i=1; i<nblig-1; i++) { n=i*tlig; p=(i-1)*tlig; q=(i+1)*tlig; for(j=1; j<nbcol-1; j++) { m=n+j; pixel = bits[m]; //pixel courant // voisinage V4 voisinage[0] = bits[p+j]; voisinage[1] = bits[q+j]; voisinage[2] = bits[m-1]; voisinage[3] = bits[m+1]; for (k=0;k<4;k++) { if ( valmin(pixel,voisinage[k])<=s && valmax(pixel,voisinage[k])>s ) { card++; contraste+=valmin(abs(s-voisinage[k]),abs(s-pixel)); } } } } if (card>0.1) { contraste*=(1/card); if (contraste>Cmoy) { Cmoy = contraste; so = s; } } }
Suivant toute logique, la 1ère version est plus rapide, les lignes déplacées ne faisant intervenir que des termes en i. Et c'est là que le bas blaisse : en réalité il n'en est rien. Suivant les mesures que j'ai pu faire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 unsigned char s; int i,j,k,n,m,p,q; unsigned char voisinage[4]; unsigned char pixel; double card, contraste; double Cmoy=0.0; unsigned char so=0; for (s=s_min; s<=s_max; s++) { contraste=0.0; card=0.0; for (i=1; i<nblig-1; i++) { n=i*tlig; for(j=1; j<nbcol-1; j++) { m=n+j; pixel = bits[m]; //pixel courant p=(i-1)*tlig; q=(i+1)*tlig; // voisinage V4 voisinage[0] = bits[p+j]; voisinage[1] = bits[q+j]; voisinage[2] = bits[m-1]; voisinage[3] = bits[m+1]; for (k=0;k<4;k++) { if ( valmin(pixel,voisinage[k])<=s && valmax(pixel,voisinage[k])>s ) { card++; contraste+=valmin(abs(s-voisinage[k]),abs(s-pixel)); } } } } if (card>0.1) { contraste*=(1/card); if (contraste>Cmoy) { Cmoy = contraste; so = s; } } }
l'exécution de la fonction 1 (à priori plus rapide) : 320ms
l'exécution de la fonction 2 (à priori plus lente) : 300ms
Les mesures sont faites sous un processus avec une priorité "temps réel" et en exécutant plusieurs fois la même fonction (moyennage). Je tiens également à préciser que ces temps d'exécution sont très très répétables dans le temps.
Que ce passe-t-il donc ?
Autre fait intérressant, si je passe le mode d'optimisation de Visual C++ 6.0 de "Maximize speed" (réglage par défaut) à "Default" (pas d'optimisation) je me retrouve avec un temps d'exécution de l'ordre de 900ms mais la fonction 1 est cette fois ci plus rapide.
Serait-ce le compilo qui pête les plombs ?
Si quelqu'un vois quelque que chose qui m'échappe là dedans et qui pourrait me permettre de comprendre pourquoi un code moins bien tapé et entrainant l'éxécution de plus d'instructions est exécuté plus rapidement merci de me faire signe !
Partager