From d3f19871d74ab2ebeee18ef16f6d8490ae82be30 Mon Sep 17 00:00:00 2001 From: rabot Date: Wed, 7 Oct 2026 11:39:55 +0200 Subject: [PATCH] =?UTF-8?q?Optimisation=20de=20l'=C3=A9cart-type=20de=20lo?= =?UTF-8?q?ngueur=20en=20r=C3=A9utilisant=20la=20moyenne=20calcul=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- analyseur.c | 7 +- notes.md | 66 ++++++++++++++ out/analyseur | Bin 27048 -> 27048 bytes out/gmon.out | Bin 8524 -> 8495 bytes out/profil_apres_moyenne.txt | 162 +++++++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 out/profil_apres_moyenne.txt diff --git a/analyseur.c b/analyseur.c index 9d6e0e7..435d719 100644 --- a/analyseur.c +++ b/analyseur.c @@ -331,11 +331,12 @@ double longueur_moyenne(const Entree *table, int 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; 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; } return somme / n; /* variance ; la racine est prise dans main */ @@ -435,7 +436,7 @@ int main(void) trier_entrees(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]; int occ_trigramme; diff --git a/notes.md b/notes.md index 3eabc97..ae60154 100644 --- a/notes.md +++ b/notes.md @@ -152,4 +152,70 @@ Empreinte du rapport : 1d53de903efd2b7c real 0m1.986s user 0m1.934s 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 ``` \ No newline at end of file diff --git a/out/analyseur b/out/analyseur index b3a384cc093341cb041675c181576ba56b69d5f1..b792c3bc60372332af9f14e30525a7032d6490ad 100755 GIT binary patch delta 1250 zcmZ2+nQ_Hs#tj^dTz{n)z~HacW+BElCXsXhJz`9>xne}_Xj|X564~KfQ)(_-0k{i@j*BYveFHPfrfASN*mhY8M`~t2YKJmvLJbCzq^yJ-! z$&7O*%NwaMmQQvuQeh05oM}|aXgv9`kuDRf;bbA>eT=S?FB)es-kEG=V$8T=a-K;E zfx)9!G=ztN0V?3pc@5+ww)c~LO|uzaPu^)N zC$;X?|NkDnQwtE64bIQZ)S|C5JbteUK2R>WvNdA^yXj4TfWLmI#S!7?6@ z+h2gZ|Km09Cw>7|W}eAc%+whlP5xsh$GCg4w7InI?zbRUxo+_2cHOXV!UbjqkIv&S z&b$K)?(pah?eOS!-2t_6^W;yLh$ZWu&x~-l@}-HSgA{`1gl)a*jT$HT$+KQ?g}Uo zfTSl(UTY;GE&dFYwD{#+7#KeD%l-1`7M-igz+m|8zv|z~53HmZPi_8f#mYL_fLUOZ z!y0D83-A8_PhnwT`0?@o{}vVo2FK6;|1V)-VA%5c|NkQ_3=9Te{{Mf%!ocw1`~UwO ztPBhSo9{Y1Gt15bMS>fjKpT@YFB{VY9(E1}1{nqhh5%*;hLp*+?(&Q|lVjcG8K+LJ zb(d#)@ow@wcR5v;_y7OzW@cbufN5mj$PCuWz`!8Fz`*c@nStTKm*R`Cll*a%5z$bn|*AK^C-+)YcT{zj$P)T3yP) z;@7(HiC-}EM0e;Fk8al+o!2}%kH1j(50ce5@rhr+^~5Lsn1hp34AsTk)A-+?{KT*2 zdj%x^;S+z{!IOtyFil=$n9SHbnaxOrF>bQ9kqV>b0~pO^g})Cx@DpFy5Mc%EV45`}P0-9-XZj|NsB@=mt~A7#KWyMXh-l7@z_k z5GTETH`&BAoAJ`*1*US0Qz!2?m0$i6S&_8dtN;H)JvyIy zG{2Dm`T7OOr67WrW%2?uNv2oalXsh`XPo3_VEDuzc@U)JN3-h}#^%~DhIN-fihrCu z{9@5dm?=jZQarj@R5chF7(6;%e;6KkvFI(x#jYDXx?MNyn{a`d0Tf=F-+={pc=U#L zcyzn&fVz3sWG{1ViCdrk|8I7k!r1NFVd*-h=IZ{2KU@qiUc8vxYwlW~{1qfQ10p%2 z=45whk4Lxb35cJMe*6C)MWFb{|Nm(o{B;LBI$bZI$ef4Cq#D396pZ z=l}nM!v2Owx9bIuUeTu<3=C=f8YjSh0h!Fiz`*c=QGc?WrJVc=4h9Ct&JUf(AoekW z?CWI}20Qlni%XNEEyMZtf^9wyQPDg3fTgUlCD?z5JbGE@f+a!e93mh34D783Aa6-R z*e5`2-pK-1>Z(tlf+A=EB!U*yT!n?;*{5J#J3uNAPL8osmzoJyxrDK?c1gH214A7s zKWzX>H%y*uB_YlJ43tj!{Pth!oU#q`TzeVEDQ{1KmY%KgoS~@^UMGLPgocj7=HZ!&%w&T zps@L_voo{oW>5sU@d>msIrFkHt>j_nU|^78U|1_pKpCI*p-j*64}g_I`u3$aaJ zDlRg)Uq}zcW@McFK~R~IX>x(M>BInu&HX}ojGOy~>KG^Y3w2HI7m}FVFO)F3Ur26p zzfjHOexbC<{X!g!jFa;O#U~#Z)c_g6%Luj@LNHEFkg%K>0G426oP0o3ezLQW&&B{H zkf}eICI)=jd{p)eWBn^J1_s6eLx`qYB?t``WH5qoR;fT}nJZ!pj0$LiU;ha)Fb1Fr zhBxywFdCRbv^hexgB-_r0Zs6g3&?r}bBNN1$Vv^Mg6wJ#Nw9tgs35B*l3>B)i3%dx z7obw%x)7;PAq)(RAE1KQ^dN#@Ll`DsP!P#buz(10L;VhxGJpzpnn5JNf&oy$rN}B1 Spn_*jkW@afgmA==v;zPQMpPmI delta 542 zcmZ4QbjE3dET@1q0~j3Hs8%k($UM>Uwj?710|N+y#CaIl8Q2&&8CV%K7?>uBgifv( z6`EWxs>jXC;>fuQK*WC@?i^`c!H1M-+A*NeJ<*b@W7Ae7VOdQq;)+Cowj1GpyF zi^@%|7gd{FFKRZqUQ}#yy(kaJO6keFZ%*envN#rq9Vb{ih zBIeC|Wxp`Go>SpvVhk_@IgNp#RtZAC5@TRsEPx75H9!(nFoJMasX%C%D`E_c4wE0s zi)bgHNrgA_GcY=sLex1z)q{e8@xx>V1(A9KbBNSKWGM%zAiEkw60AM}D#)sdBsc*o zSf~XN{1n2#!1w?v7_N&X$Y25CT+@TlU^4|cp`ud_CSOz#PT+?67A)xim0M(nq$2?; WxDQ!n0aWmr36jbWmJp6Ul6C+Vu2Nh8 diff --git a/out/profil_apres_moyenne.txt b/out/profil_apres_moyenne.txt new file mode 100644 index 0000000..041505e --- /dev/null +++ b/out/profil_apres_moyenne.txt @@ -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 + +[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