Optimisation de l'écart-type de longueur en réutilisant la moyenne calculée

This commit is contained in:
rabot
2026-10-07 11:39:55 +02:00
parent be387e2066
commit d3f19871d7
5 changed files with 232 additions and 3 deletions
+4 -3
View File
@@ -331,11 +331,12 @@ double longueur_moyenne(const Entree *table, int n)
return (double)total / n; return (double)total / n;
} }
double ecart_type_longueur(const Entree *table, int n) /* Réutiliser la moyenne calculée dans main évite de la recalculer par mot. */
double ecart_type_longueur(const Entree *table, int n, double moyenne)
{ {
double somme = 0.0; double somme = 0.0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
double ecart = longueur(table[i].mot) - longueur_moyenne(table, n); double ecart = longueur(table[i].mot) - moyenne;
somme += ecart * ecart; somme += ecart * ecart;
} }
return somme / n; /* variance ; la racine est prise dans main */ return somme / n; /* variance ; la racine est prise dans main */
@@ -435,7 +436,7 @@ int main(void)
trier_entrees(table, nb_entrees); trier_entrees(table, nb_entrees);
double moyenne = longueur_moyenne(table, nb_entrees); double moyenne = longueur_moyenne(table, nb_entrees);
double ecart_type = racine(ecart_type_longueur(table, nb_entrees)); double ecart_type = racine(ecart_type_longueur(table, nb_entrees, moyenne));
char trigramme[4]; char trigramme[4];
int occ_trigramme; int occ_trigramme;
+66
View File
@@ -153,3 +153,69 @@ real 0m1.986s
user 0m1.934s user 0m1.934s
sys 0m0.011s sys 0m0.011s
``` ```
## Optimisation des appels à `longueur_moyenne`
`longueur_moyenne` parcourt les mots une fois par appel. Le coût excessif
venait de `ecart_type_longueur`, qui recalculait cette même moyenne à
chaque itération, soit 5 866 fois. Avec l'appel de `main`, cela représentait
5 867 calculs de moyenne et 34 415 822 appels à `longueur()`.
`main` calcule désormais la moyenne une seule fois et la transmet en
paramètre à `ecart_type_longueur`. La boucle utilise directement cette
valeur. Le calcul des statistiques passe ainsi de O(n²) à O(n), sans
allocation supplémentaire ni modification de la formule de variance.
Profil enregistré dans [out/profil_apres_moyenne.txt](out/profil_apres_moyenne.txt).
La colonne « Avant » correspond à la version déjà optimisée pour
`chercher_mot`, dont le profil reste dans `out/profil_apres.txt`.
| Mesure | Avant | Après |
| --- | ---: | ---: |
| Appels à `longueur_moyenne` | 5 867 | 1 |
| Appels à `longueur()` depuis `longueur_moyenne` | 34 415 822 | 5 866 |
| Appels à `longueur()` dans tout le programme | 36 009 819 | 1 599 863 |
| Temps réel sans profiling (`gcc -O0`) | 1,46 s | 0,88 s |
Cette mesure ponctuelle sur la même machine donne environ 40 % de temps
en moins, soit une accélération d'environ 1,66 par rapport à l'étape précédente.
Validation : compilation avec `-Wall -Wextra -Wpedantic` sans avertissement,
puis comparaison du rapport et de la sortie console avant/après, avec et
sans `-pg`. Ils restent identiques octet par octet, y compris la moyenne
(`6.712`) et l'écart-type (`1.873`). L'empreinte reste **`1d53de903efd2b7c`**.
Commandes pour reproduire ce profil :
```bash
mkdir -p out/apres_moyenne
gcc -O0 -pg analyseur.c -o out/apres_moyenne/analyseur
(cd out/apres_moyenne && ./analyseur && gprof -b ./analyseur gmon.out > ../profil_apres_moyenne.txt)
```
```bash
[rabot@salle235-06 out]$ time ./analyseur
Lignes analysées : 21746
Mots au total : 250000
Mots distincts : 5866
Longueur moyenne : 6.712 (écart-type 1.873)
Bigramme le + courant : "me" (17607 fois, souvent suivi de 'n')
Top 10 :
1. rane 287
2. fasi 241
3. tata 219
4. mopo 214
5. cofi 180
6. vesi 179
7. laganomo 177
8. boto 172
9. nopebo 169
10. rotion 165
Empreinte du rapport : 1d53de903efd2b7c
real 0m1.251s
user 0m1.214s
sys 0m0.004s
```
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+162
View File
@@ -0,0 +1,162 @@
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
61.33 0.46 0.46 1599863 0.00 0.00 longueur
12.00 0.55 0.09 9860216 0.00 0.00 comparer
8.00 0.61 0.06 1 60.00 164.31 trier_entrees
4.00 0.64 0.03 17202045 0.00 0.00 doit_echanger
4.00 0.67 0.03 12045671 0.00 0.00 egales
4.00 0.70 0.03 150182 0.00 0.00 compter_mot
1.33 0.71 0.01 5297256 0.00 0.00 est_lettre
1.33 0.72 0.01 250000 0.00 0.00 est_mot_vide
1.33 0.73 0.01 150182 0.00 0.00 chercher_mot
1.33 0.74 0.01 1 10.00 17.09 analyser_bigrammes
1.33 0.75 0.01 1 10.00 10.00 generer_texte
0.00 0.75 0.00 1266663 0.00 0.00 en_minuscule
0.00 0.75 0.00 928117 0.00 0.00 alea
0.00 0.75 0.00 32667 0.00 0.00 copier
0.00 0.75 0.00 26801 0.00 0.00 ajouter
0.00 0.75 0.00 21746 0.00 0.00 compter_mots_ligne
0.00 0.75 0.00 21746 0.00 0.02 normaliser_ligne
0.00 0.75 0.00 1 0.00 1.69 construire_rapport
0.00 0.75 0.00 1 0.00 0.00 decouper_lignes
0.00 0.75 0.00 1 0.00 1.69 ecart_type_longueur
0.00 0.75 0.00 1 0.00 0.00 empreinte
0.00 0.75 0.00 1 0.00 6.02 generer_vocabulaire
0.00 0.75 0.00 1 0.00 1.69 longueur_moyenne
0.00 0.75 0.00 1 0.00 0.00 racine
Call graph
granularity: each sample hit covers 4 byte(s) for 1.33% of 0.75 seconds
index % time self children called name
<spontaneous>
[1] 100.0 0.00 0.75 main [1]
0.00 0.45 21746/21746 normaliser_ligne [3]
0.06 0.10 1/1 trier_entrees [4]
0.00 0.10 21746/21746 compter_mots_ligne [6]
0.01 0.01 1/1 analyser_bigrammes [12]
0.01 0.00 1/1 generer_texte [14]
0.00 0.01 1/1 generer_vocabulaire [16]
0.00 0.00 1/1 construire_rapport [17]
0.00 0.00 1/1 longueur_moyenne [19]
0.00 0.00 1/1 ecart_type_longueur [18]
0.00 0.00 1/1 decouper_lignes [23]
0.00 0.00 1/1 racine [25]
0.00 0.00 1/1 empreinte [24]
-----------------------------------------------
0.00 0.00 5866/1599863 longueur_moyenne [19]
0.00 0.00 5866/1599863 ecart_type_longueur [18]
0.01 0.00 26801/1599863 ajouter [15]
0.45 0.00 1561330/1599863 normaliser_ligne [3]
[2] 61.3 0.46 0.00 1599863 longueur [2]
-----------------------------------------------
0.00 0.45 21746/21746 main [1]
[3] 60.2 0.00 0.45 21746 normaliser_ligne [3]
0.45 0.00 1561330/1599863 longueur [2]
0.00 0.00 1539584/5297256 est_lettre [13]
0.00 0.00 1266663/1266663 en_minuscule [20]
-----------------------------------------------
0.06 0.10 1/1 main [1]
[4] 21.9 0.06 0.10 1 trier_entrees [4]
0.03 0.07 17202045/17202045 doit_echanger [5]
-----------------------------------------------
0.03 0.07 17202045/17202045 trier_entrees [4]
[5] 13.9 0.03 0.07 17202045 doit_echanger [5]
0.07 0.00 8141769/9860216 comparer [7]
-----------------------------------------------
0.00 0.10 21746/21746 main [1]
[6] 12.8 0.00 0.10 21746 compter_mots_ligne [6]
0.03 0.03 150182/150182 compter_mot [8]
0.01 0.03 250000/250000 est_mot_vide [9]
-----------------------------------------------
0.02 0.00 1718447/9860216 chercher_mot [11]
0.07 0.00 8141769/9860216 doit_echanger [5]
[7] 12.0 0.09 0.00 9860216 comparer [7]
-----------------------------------------------
0.03 0.03 150182/150182 compter_mots_ligne [6]
[8] 7.4 0.03 0.03 150182 compter_mot [8]
0.01 0.02 150182/150182 chercher_mot [11]
0.00 0.00 5866/32667 copier [22]
-----------------------------------------------
0.01 0.03 250000/250000 compter_mots_ligne [6]
[9] 5.3 0.01 0.03 250000 est_mot_vide [9]
0.03 0.00 12045671/12045671 egales [10]
-----------------------------------------------
0.03 0.00 12045671/12045671 est_mot_vide [9]
[10] 4.0 0.03 0.00 12045671 egales [10]
-----------------------------------------------
0.01 0.02 150182/150182 compter_mot [8]
[11] 3.4 0.01 0.02 150182 chercher_mot [11]
0.02 0.00 1718447/9860216 comparer [7]
-----------------------------------------------
0.01 0.01 1/1 main [1]
[12] 2.3 0.01 0.01 1 analyser_bigrammes [12]
0.01 0.00 3757672/5297256 est_lettre [13]
-----------------------------------------------
0.00 0.00 1539584/5297256 normaliser_ligne [3]
0.01 0.00 3757672/5297256 analyser_bigrammes [12]
[13] 1.3 0.01 0.00 5297256 est_lettre [13]
-----------------------------------------------
0.01 0.00 1/1 main [1]
[14] 1.3 0.01 0.00 1 generer_texte [14]
0.00 0.00 900183/928117 alea [21]
-----------------------------------------------
0.00 0.00 5867/26801 construire_rapport [17]
0.00 0.01 20934/26801 generer_vocabulaire [16]
[15] 1.0 0.00 0.01 26801 ajouter [15]
0.01 0.00 26801/1599863 longueur [2]
0.00 0.00 26801/32667 copier [22]
-----------------------------------------------
0.00 0.01 1/1 main [1]
[16] 0.8 0.00 0.01 1 generer_vocabulaire [16]
0.00 0.01 20934/26801 ajouter [15]
0.00 0.00 27934/928117 alea [21]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[17] 0.2 0.00 0.00 1 construire_rapport [17]
0.00 0.00 5867/26801 ajouter [15]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[18] 0.2 0.00 0.00 1 ecart_type_longueur [18]
0.00 0.00 5866/1599863 longueur [2]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[19] 0.2 0.00 0.00 1 longueur_moyenne [19]
0.00 0.00 5866/1599863 longueur [2]
-----------------------------------------------
0.00 0.00 1266663/1266663 normaliser_ligne [3]
[20] 0.0 0.00 0.00 1266663 en_minuscule [20]
-----------------------------------------------
0.00 0.00 27934/928117 generer_vocabulaire [16]
0.00 0.00 900183/928117 generer_texte [14]
[21] 0.0 0.00 0.00 928117 alea [21]
-----------------------------------------------
0.00 0.00 5866/32667 compter_mot [8]
0.00 0.00 26801/32667 ajouter [15]
[22] 0.0 0.00 0.00 32667 copier [22]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[23] 0.0 0.00 0.00 1 decouper_lignes [23]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[24] 0.0 0.00 0.00 1 empreinte [24]
-----------------------------------------------
0.00 0.00 1/1 main [1]
[25] 0.0 0.00 0.00 1 racine [25]
-----------------------------------------------
Index by function name
[15] ajouter [22] copier [9] est_mot_vide
[21] alea [23] decouper_lignes [14] generer_texte
[12] analyser_bigrammes [5] doit_echanger [16] generer_vocabulaire
[11] chercher_mot [18] ecart_type_longueur [2] longueur
[7] comparer [10] egales [19] longueur_moyenne
[8] compter_mot [24] empreinte [3] normaliser_ligne
[6] compter_mots_ligne [20] en_minuscule [25] racine
[17] construire_rapport [13] est_lettre [4] trier_entrees