Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 09578cece8 | |||
| ce8b4b9fb4 | |||
| 103ae34f6a |
+118
@@ -0,0 +1,118 @@
|
||||
# Compte-rendu TD1
|
||||
|
||||
**Nom Binôme :** Luka PLOUVIER et Jimmy COLOMB-RAVAT
|
||||
|
||||
## 1. Mesurer
|
||||
|
||||
**Empreinte du rapport :** `1d53de903efd2b7c`
|
||||
|
||||
```text
|
||||
real 0m2.638s
|
||||
user 0m2.613s
|
||||
sys 0m0.004s
|
||||
```
|
||||
|
||||
## 3. Analyser
|
||||
|
||||
### Profil plat :
|
||||
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
39.12 0.84 0.84 308701874 0.00 0.00 egales
|
||||
32.41 1.54 0.70 36009819 0.00 0.00 longueur
|
||||
12.04 1.80 0.26 150182 0.00 0.01 chercher_mot
|
||||
```
|
||||
|
||||
La plupart du temps d'exécution se passe par ces fonctions.
|
||||
En observant le code, on se rend compte qu'il est difficile d'optimiser les fonctions `egales` et `longueur`.
|
||||
|
||||
### Graphe d'appels :
|
||||
|
||||
Dans `ecart_type_longueur` on voit qu'elle appelle `longueur_moyenne` pour chaque mot unique alors que la moyenne est déjà calculée dans le `main`.
|
||||
|
||||
```text
|
||||
0.00 0.00 1/5867 main [1]
|
||||
0.07 0.67 5866/5867 ecart_type_longueur [7]
|
||||
[6] 34.2 0.07 0.67 5867 longueur_moyenne [6]
|
||||
0.67 0.00 34415822/36009819 longueur [8]
|
||||
```
|
||||
|
||||
`longueur_moyenne` appelle 34.4 millions de fois `longueur` soit 95% des 36 millions d'appels pour 34.2% du temps total.
|
||||
|
||||
`chercher_mot` fait une recherche linéaire pour chacune des 150 182 occurrences. Comme la table grandit jusqu'à 5866 entrées, c'est un comptage de mots x mots_uniques soit 296,6 millions d'appels à `égales` sur les 308,7 millions d'appels au total.
|
||||
|
||||
## 4. Proposer
|
||||
|
||||
* Faire une table de hachage pour le comptage des mots dans `chercher_mot`.
|
||||
* Calculer la moyenne une seule fois dans `ecart_type_longueur`.
|
||||
|
||||
## 5. Optimiser
|
||||
|
||||
**Comparaison des appels à `egales` :**
|
||||
|
||||
*Avant :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
39.12 0.84 0.84 308701874 0.00 0.00 egales
|
||||
```
|
||||
|
||||
*Après :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
2.25 1.03 0.03 12195414 0.00 0.00 egales
|
||||
```
|
||||
|
||||
On peut voir que le nombre d'appels de `egales` a diminué de près de 296 millions.
|
||||
|
||||
```text
|
||||
real 0m1.867s
|
||||
user 0m1.829s
|
||||
sys 0m0.000s
|
||||
```
|
||||
|
||||
Le temps d'exécution a diminué de 0,8 seconde.
|
||||
|
||||
**Comparaison des appels à `longueur` :**
|
||||
|
||||
*Avant :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
63.06 0.70 0.70 36009819 0.00 0.00 longueur
|
||||
```
|
||||
|
||||
*Après :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
66.67 0.46 0.46 1605729 0.00 0.00 longueur
|
||||
```
|
||||
|
||||
**Comparaison des appels à `longueur_moyenne` :**
|
||||
|
||||
*Avant :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
9.91 0.81 0.11 5867 0.02 0.13 longueur_moyenne
|
||||
```
|
||||
|
||||
*Après :*
|
||||
```text
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
0.00 0.69 0.00 2 0.00 1.68 longueur_moyenne
|
||||
```
|
||||
|
||||
On peut voir qu'on a diminué le nombre d'appels de `longueur` de 34,4 millions d'appels environ en n'appelant qu'une seule fois `longueur_moyenne` dans `ecart_type_longueur`.
|
||||
|
||||
```text
|
||||
real 0m1.205s
|
||||
user 0m1.167s
|
||||
sys 0m0.000s
|
||||
```
|
||||
|
||||
On a encore diminué le temps d'exécution de 0.8 seconde.
|
||||
+45
-10
@@ -217,6 +217,16 @@ void normaliser_ligne(char *ligne)
|
||||
}
|
||||
}
|
||||
|
||||
#define TAILLE_HACHAGE 65536 // Puissance de 2, bien plus grand que MAX_MOTS_UNIQUES
|
||||
|
||||
unsigned int hacher(const char *mot) {
|
||||
unsigned int h = 5381;
|
||||
for (int i = 0; mot[i] != '\0'; i++) {
|
||||
h = ((h << 5) + h) + (unsigned char)mot[i]; /* équivalent à h * 33 + c */
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Comptage des mots */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -235,29 +245,44 @@ int est_mot_vide(const char *mot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chercher_mot(Entree *table, int nb_entrees, const char *mot)
|
||||
int chercher_mot(Entree *table, int *table_hachage, const char *mot, int *pos_libre)
|
||||
{
|
||||
for (int i = 0; i < nb_entrees; i++) {
|
||||
if (egales(table[i].mot, mot))
|
||||
return i;
|
||||
unsigned int h = hacher(mot) & (TAILLE_HACHAGE - 1);
|
||||
|
||||
while (table_hachage[h] != -1) {
|
||||
int indice = table_hachage[h];
|
||||
if (egales(table[indice].mot, mot)) {
|
||||
return indice; // Le mot a été trouvé
|
||||
}
|
||||
h = (h + 1) & (TAILLE_HACHAGE - 1); // Résolution de collision (sondage linéaire)
|
||||
}
|
||||
|
||||
// Si on arrive ici, le mot n'est pas dans la table
|
||||
if (pos_libre != NULL) {
|
||||
*pos_libre = h; // On sauvegarde l'emplacement libre pour l'insertion
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void compter_mot(Entree *table, int *nb_entrees, const char *mot)
|
||||
void compter_mot(Entree *table, int *nb_entrees, const char *mot, int *table_hachage)
|
||||
{
|
||||
int indice = chercher_mot(table, *nb_entrees, mot);
|
||||
int pos_libre;
|
||||
int indice = chercher_mot(table, table_hachage, mot, &pos_libre);
|
||||
|
||||
if (indice >= 0) {
|
||||
table[indice].occurrences++;
|
||||
} else {
|
||||
// Insertion du nouveau mot à la suite de la table classique
|
||||
copier(table[*nb_entrees].mot, mot);
|
||||
table[*nb_entrees].occurrences = 1;
|
||||
// On mémorise son index dans la table de hachage
|
||||
table_hachage[pos_libre] = *nb_entrees;
|
||||
(*nb_entrees)++;
|
||||
}
|
||||
}
|
||||
|
||||
void compter_mots_ligne(Entree *table, int *nb_entrees, const char *ligne,
|
||||
long *nb_mots_total)
|
||||
long *nb_mots_total, int *table_hachage)
|
||||
{
|
||||
char mot[TAILLE_MOT];
|
||||
int i = 0;
|
||||
@@ -275,7 +300,7 @@ void compter_mots_ligne(Entree *table, int *nb_entrees, const char *ligne,
|
||||
if (k > 0) {
|
||||
(*nb_mots_total)++;
|
||||
if (!est_mot_vide(mot))
|
||||
compter_mot(table, nb_entrees, mot);
|
||||
compter_mot(table, nb_entrees, mot, table_hachage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,8 +344,11 @@ double longueur_moyenne(const Entree *table, int n)
|
||||
double ecart_type_longueur(const Entree *table, int n)
|
||||
{
|
||||
double somme = 0.0;
|
||||
// On calcule la moyenne une seule fois avant la boucle
|
||||
double moyenne = longueur_moyenne(table, n);
|
||||
|
||||
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 */
|
||||
@@ -412,10 +440,16 @@ int main(void)
|
||||
normaliser_ligne(lignes[i]);
|
||||
|
||||
Entree *table = malloc(MAX_MOTS_UNIQUES * sizeof(Entree));
|
||||
|
||||
int *table_hachage = malloc(TAILLE_HACHAGE * sizeof(int));
|
||||
for (int i = 0; i < TAILLE_HACHAGE; i++) {
|
||||
table_hachage[i] = -1; // -1 indique une case vide
|
||||
}
|
||||
|
||||
int nb_entrees = 0;
|
||||
long nb_mots_total = 0;
|
||||
for (int i = 0; i < nb_lignes; i++)
|
||||
compter_mots_ligne(table, &nb_entrees, lignes[i], &nb_mots_total);
|
||||
compter_mots_ligne(table, &nb_entrees, lignes[i], &nb_mots_total, table_hachage);
|
||||
|
||||
trier_entrees(table, nb_entrees);
|
||||
|
||||
@@ -446,6 +480,7 @@ int main(void)
|
||||
|
||||
free(rapport);
|
||||
free(table);
|
||||
free(table_hachage);
|
||||
for (int i = 0; i < nb_lignes; i++)
|
||||
free(lignes[i]);
|
||||
free(lignes);
|
||||
|
||||
Reference in New Issue
Block a user