Optimise la normalisation avec une table de conversion

This commit is contained in:
rabot
2026-10-07 15:43:48 +02:00
parent 2abe610d58
commit 19ad9b7b33
5 changed files with 427 additions and 18 deletions
+90 -1
View File
@@ -600,4 +600,93 @@ Empreinte du rapport : 1d53de903efd2b7c
real 0m0.078s
user 0m0.059s
sys 0m0.001s
```
```
## Table de conversion pour `normaliser_ligne`
Une table de 256 cases mémorise le résultat de la normalisation de chaque
octet. Elle est initialisée au premier appel : les majuscules deviennent
des minuscules, les minuscules sont conservées et les autres caractères
deviennent des espaces. La boucle applique ensuite directement
`conversion[(unsigned char)ligne[i]]`, jusqu'au premier `\0`.
La conversion en `unsigned char` garantit un indice entre 0 et 255,
y compris pour les octets supérieurs à 127. Le comportement reste celui
du programme initial : seules les lettres ASCII sont conservées.
Les fonctions `est_lettre` et `en_minuscule`, devenues inutilisées, sont
supprimées. Le parcours reste en O(longueur de la ligne), avec moins de
tests et sans appel de fonction pour chaque caractère.
La table occupe 256 octets, auxquels s'ajoute l'indicateur d'initialisation
de 4 octets sur cette machine, sans allocation dynamique.
Profil enregistré dans [out/profil_apres_normalisation.txt](out/profil_apres_normalisation.txt).
La comparaison porte sur la version précédente, décrite dans
`out/profil_apres_mots_vides.txt`.
| Mesure | Avant | Après |
| --- | ---: | ---: |
| Appels à `normaliser_ligne` | 21 746 | 21 746 |
| Appels à `est_lettre` | 1 539 584 | 0 |
| Appels à `en_minuscule` | 1 266 663 | 0 |
| Temps réel médian sans profiling (`gcc -O0`, 10 exécutions par version) | 0,0577 s | 0,0508 s |
Le gain médian mesuré est de 11,9 %. Les mesures ont été réalisées en
alternant les deux versions sur la même machine :
- Avant : 0,0578 / 0,0587 / 0,0577 / 0,0574 / 0,0569 / 0,0573 / 0,0576 /
0,0572 / 0,0580 / 0,0583 s.
- Après : 0,0506 / 0,0509 / 0,0528 / 0,0511 / 0,0506 / 0,0503 / 0,0508 /
0,0512 / 0,0512 / 0,0503 s.
Validation : compilation sans avertissement avec `-Wall -Wextra -Wpedantic`,
rapport et sortie console identiques octet par octet sur les vingt
exécutions, avec `-pg` et sous AddressSanitizer et UndefinedBehaviorSanitizer.
L'empreinte reste **`1d53de903efd2b7c`**.
Des tests temporaires ont comparé la nouvelle fonction à l'ancienne sur
les 256 valeurs d'octet, une ligne vide, des caractères mélangés, des
octets après le premier zéro et une ligne de 65 536 octets. Ils vérifient
aussi qu'une seconde normalisation ne change plus le résultat, avec
`-fsigned-char` et `-funsigned-char`.
Commandes pour reproduire ce profil :
```bash
mkdir -p out/apres_normalisation
gcc -O0 -pg analyseur.c -o out/apres_normalisation/analyseur
(cd out/apres_normalisation && ./analyseur && gprof -b ./analyseur gmon.out > ../profil_apres_normalisation.txt)
```
## Vérification de la normalisation sur le même PC
Pour vérifier le gain malgré les changements de machine, les deux versions
ont été recompilées et comparées directement sur **salle235-06**, équipé
d'un **Intel Core i7-8700 à 3,20 GHz**, avec **GCC 16.2.1**.
La référence est le commit `1331811`, juste après l'optimisation de
`est_mot_vide`. La version comparée est le fichier `analyseur.c` avec la
table de conversion de `normaliser_ligne`. La différence de code porte
uniquement sur cette normalisation et la suppression des deux fonctions
utilitaires devenues inutilisées.
Protocole : mêmes options `-std=c11 -Wall -Wextra -Wpedantic -O0`, sans
`-pg`, cinq exécutions de chauffe par version, puis **50 mesures par
version**. Les versions sont exécutées successivement, en inversant
l'ordre à chaque paire, sur le même CPU logique (CPU 0). Le temps CPU
correspond à la somme des temps utilisateur et système du programme.
| Mesure médiane | Après `est_mot_vide` | Avec la nouvelle normalisation | Temps gagné |
| --- | ---: | ---: | ---: |
| Temps réel | 56,91 ms | 50,83 ms | 10,7 % |
| Temps CPU | 56,35 ms | 50,35 ms | 10,7 % |
La nouvelle version est plus rapide dans **50 paires sur 50**, en temps
réel comme en temps CPU. Le gain de la normalisation est donc confirmé
sur cette machine avec `-O0`. Il représente environ 6 ms par exécution.
Le rapport et la sortie console sont identiques sur les **110 exécutions**,
chauffe incluse. L'empreinte reste **`1d53de903efd2b7c`**.
Les [100 mesures brutes](out/comparaison_normalisation_meme_pc.csv) sont
conservées, ainsi que les [conditions et statistiques détaillées](out/comparaison_normalisation_meme_pc.json),
qui identifient le commit de référence et les deux sources utilisées.