Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1242 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Probleme d'indirection sur structures

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Probleme d'indirection sur structures

n°1298423
julien_54
Posté le 03-02-2006 à 11:47:26  profilanswer
 

Bonjour, :hello:  
 
tout part d'un bon gros programme en C, à base de plusieurs structures qui s'entremelent (j'aurais preferé le faire en objet, mais je n'avais pas le choix du langage...).
Une structure A posséde un champ qui est un tableau de structure B. Mon premier reflexe a alors été de créer un tableau de pointeurs sur struct B dans A (ce qui donnait struct B **tab_b).
On pouvait alors accéder aux champs de B avec A->B[i]->champ
Ensuite, relisant mon code, et suite à plusieurs discussions, j'ai décidé qu'il était inutile de surcharger la mémoire avec un tableau de pointeurs, mais plutot mettre  
directement un tableau de structures... je me suis dit qu'avec une indirection en moins, cela accelererait le code. Donc c'est parti, maintenant j'ai struct B *tab_b dans A,
et j'y accède avec A->B[i].champ (on modifiant bien evidemment la façon d'allouer la mémoire et tout ce qui va avece pour que cette méthode fonctionne)
Et là, je suis etonné, mais il semble que cela ralentisse l'execution. (le programme fonctionne parfaitement, mes tests sont OK, tout va bien)
 
Qu'en pensez vous ? Avant tout, cette méthode de gestion des tableaux de structure est elle correcte, ou vaut il mieux garder des tableau de pointeurs lorsque les deux méthodes sont possibles (plus propre ?)
Moi je pense que l'optimiseur du compilo se demerdait mieux avec un tableau de pointeur. Je pense aussi qu'avec cette modif, il a plus de mémoire  
à manipuler pour réallouer... Ou alors, c'est ma methode de mesure du temps d'execution qui n'est pas correcte.
 
Avant toute réponse j'entend bien que certains cas ne sont exclusivements possibles qu'avec l'une ou l'autre méthode ; dans mon cas, je ne parle que des cas de  
figures pour lesquelles il est possible de faire les deux (soit un tableau de pointeurs sur structure, soit un tableau de structure)
 
Merci pour ceux qui prendront le temps ... :-)

mood
Publicité
Posté le 03-02-2006 à 11:47:26  profilanswer
 

n°1298435
skelter
Posté le 03-02-2006 à 11:56:51  profilanswer
 

aloue un tableau d'objets plutot qu'un tableau de pointeurs sur objets si tu n'en a pas besoin, c'est plus simple, plus sur et certainement plus efficace (memoire moins fragementée, acces avec une indirection en moins...), et bien sur pas d'allocation dynamique si la taille est connue à la compilation


Message édité par skelter le 03-02-2006 à 11:57:13
n°1298437
chrisbk
-
Posté le 03-02-2006 à 11:58:47  profilanswer
 

vérifie que tu fasses pas des recopies de A, peut etre ?

n°1298443
julien_54
Posté le 03-02-2006 à 12:01:14  profilanswer
 

chrisbk a écrit :

vérifie que tu fasses pas des recopies de A, peut etre ?


 
Désolé comprend pas .... :heink:  :sweat:

n°1298445
chrisbk
-
Posté le 03-02-2006 à 12:04:47  profilanswer
 

ah merde, non, rien [:petrus75]

n°1298609
julien_54
Posté le 03-02-2006 à 15:31:28  profilanswer
 

Bon je viens de reessayer avec la version d'avant et bien y a bien une difference de vitesse d'execution ... donc comprend pas, comme si le '.' est moins bien géré que la '->' ...

n°1298618
skelter
Posté le 03-02-2006 à 15:44:17  profilanswer
 

'->' est juste un sucre syntaxique, p-> est strictement équivalent à (*p).
 
tu peux montrer ton code de test ou tu compare les 2 méthodes ?

n°1298633
julien_54
Posté le 03-02-2006 à 15:57:35  profilanswer
 

ba en fait non ... :/  
C un assez gros prog (programme de reco automatique de la parole)...
J'utilise CVS et avant de supprimer les indirections superflues, j'ai commité mon prog.
Ensuite j'ai fait mes modifs (suppression des indirections, modification des allocations dynamiques etc...).
 
Dans ce code, j'ai une partie critique qui doit etre la plus optimisée possible (mon algo de reco doit le faire en temps reel : 1 seconde d'execution pour le traitement de 10000 vecteurs à 36 dimensions). J'ai donc entourée cette partie d'un clock() et renvoyé la différence (avec la division qui va bien pour l'avoir en seconde).
 
Du coup j'ai pu tester le prog non modifié (4.75 secondes) (checkout du CVS dans un autre dossier) et le prog modifié (4.98 secondes) (la version non commitée du prog). Je l'ai fait plusieurs fois pour avoir une moyenne bien entendu...
 
La différence sera significative lorsque je traiterai des fichiers d'1 heure...
 
A priori il n'y a pas de grosse imperfection dans le prog puisqu'il fonctionne ( :-) ) et que Insure me dit qu'il n'y a pas d'erreurs detectée (debordement memoire, lecture de pointeurs NULL, ...)
 
Donc comprend pas, m'aurait on trompé ?

n°1298666
0x90
Posté le 03-02-2006 à 16:26:24  profilanswer
 

Au pif, si ta structure est sensiblement plus grosse que les pointeurs et selon l'ordre de tes accès ptètre qu'une différence se fait dans la gestion du cache processeur.


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1298672
skelter
Posté le 03-02-2006 à 16:35:11  profilanswer
 

elle fais quel taille la structure A ? tu compiles avec quoi et avec quels options ?

mood
Publicité
Posté le 03-02-2006 à 16:35:11  profilanswer
 

n°1298695
julien_54
Posté le 03-02-2006 à 16:58:52  profilanswer
 

compilation : gcc -lm -Wall -ansi -O3
 
Et oui effectivement ma structure est largement plus grosse qu'un pointeur. C'est plus compliqué que deux structures A et B ... en moyenne on va dire qu'une structure dans mon programme fait 24 octets (en profondeur 1 : c'est à dire un pointeur = 4).

n°1298714
skelter
Posté le 03-02-2006 à 17:19:14  profilanswer
 

24 octets c'est pas grand chose, sans tableau de pointeur c'est plus cache-friendly
tu fais quoi comme traitement sur ces tableaux ?

n°1300339
julien_54
Posté le 07-02-2006 à 10:10:29  profilanswer
 

Désolé de pas avoir répondu avant ...
 
En fait, je fais principalement de l'accès aux données des structures dans les tableaux, mais aussi un peu de modif ; la partie dont je mesure le temps d'execution de comprend pas de malloc pas de realloc juste des lectures et quelques ecritures dans ces tableaux de structures ...

n°1300419
skelter
Posté le 07-02-2006 à 12:27:37  profilanswer
 

faudrais que tu montres un peu de code, le minimun pour les 2 cas :

  • la définition des structure
  • le code simplifié du traitement (la ou se fait la différence de perf) en une 20aines de lignes max


n°1300536
Sve@r
Posté le 07-02-2006 à 15:12:34  profilanswer
 

julien_54 a écrit :

Une structure A posséde un champ qui est un tableau de structure B. Mon premier reflexe a alors été de créer un tableau de pointeurs sur struct B dans A (ce qui donnait struct B **tab_b).
On pouvait alors accéder aux champs de B avec A->B[i]->champ


En lisant ta description moi j'aurais plutôt écrit "A.B[i]->champ". Mais c'est un détail, "A" doit probablement être un pointeur sur une "struct A"...
 

julien_54 a écrit :

Ensuite, relisant mon code, et suite à plusieurs discussions, j'ai décidé qu'il était inutile de surcharger la mémoire avec un tableau de pointeurs, mais plutot mettre directement un tableau de structures... je me suis dit qu'avec une indirection en moins, cela accelererait le code. Donc c'est parti, maintenant j'ai struct B *tab_b dans A,
et j'y accède avec A->B[i].champ


Idem remarque précédente...
 

julien_54 a écrit :

Et là, je suis etonné, mais il semble que cela ralentisse l'execution.


 
Premier cas:
Tu as des tas de structures B un peu partout
Tu as aussi une structure A qui contient les adresses de chaque structure B
On peut schématiquement représenter ça (c'est pas évident sans dessin) où toutes ces structures B baguenaudent de ci, de là (instant poésie)... mais tu as chaque fois leurs adresses pour les référencer. Pour simplifier, ce serait presque comme une liste chaînée ou une inode. Mais la structure A reste elle-même très légère car elle ne mémorise que des adresses.
 
Second cas
Ta structure A a été modifiée et contient maintenant l'ensemble de tes structures B qui se suivent en mémoire. Elle est maintenant bien plus lourde à gérer.
A chaque fois que tu fais "A.B[i]" le compilo doit décaler non pas de "i * sizeof(adresse)" octets mais "i * sizeof(B)" octets. Plus de calcul => plus de temps...
 

julien_54 a écrit :

Qu'en pensez vous ? Avant tout, cette méthode de gestion des tableaux de structure est elle correcte, ou vaut il mieux garder des tableau de pointeurs lorsque les deux méthodes sont possibles (plus propre ?)


Je pense que si tu regardes comment est fait l'inode, tu auras déjà un bon point de repère.
 

julien_54 a écrit :

Moi je pense que l'optimiseur du compilo se demerdait mieux avec un tableau de pointeur. Je pense aussi qu'avec cette modif, il a plus de mémoire à manipuler pour réallouer...


T'as gagné. A une époque on gagnait du temps de calcul sur les tableaux de structures en les taillant à une taille pile poil puissance de 2 (256, 512, 1024, 2048, etc) car cela tombait sur des mots mémoires et l'optimiseurs pouvait décaler plus rapidement mais je ne sais pas si c'est encore utile aujourd'hui. Tu peux essayer de générer l'assembleur pour chaqu'un de tes 2 cas et voir la taille du source généré. C'est un bon point de repère. Mais je pense que le tableau d'adresses est encore ce qu'il y a de plus rapide.

Message cité 2 fois
Message édité par Sve@r le 07-02-2006 à 15:15:46

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1300561
skelter
Posté le 07-02-2006 à 15:29:29  profilanswer
 

Sve@r a écrit :

A chaque fois que tu fais "A.B[i]" le compilo doit décaler non pas de "i * sizeof(adresse)" octets mais "i * sizeof(B)" octets. Plus de calcul => plus de temps...


 
c'est la meme chose ??  
avec la premiere methode tout est fragementé avec une indirection en plus lors de l'acces, ca dois forcement compter ?

n°1300669
julien_54
Posté le 07-02-2006 à 17:34:05  profilanswer
 

Sve@r a écrit :

En lisant ta description moi j'aurais plutôt écrit "A.B[i]->champ". Mais c'est un détail, "A" doit probablement être un pointeur sur une "struct A"...
 
Exactement (bonne remarque...)
 
Idem remarque précédente...
 
  :sweat:  
 
Premier cas:
Tu as des tas de structures B un peu partout
Tu as aussi une structure A qui contient les adresses de chaque structure B
On peut schématiquement représenter ça (c'est pas évident sans dessin) où toutes ces structures B baguenaudent de ci, de là (instant poésie)... mais tu as chaque fois leurs adresses pour les référencer. Pour simplifier, ce serait presque comme une liste chaînée ou une inode. Mais la structure A reste elle-même très légère car elle ne mémorise que des adresses.
 
Si l'on m'avait dit que l'on peut faire de la poésie en parlant d'allocation mémoire en C ...
 
C'est quoi inode ? (je vais demander à mon ami Google ...)
 
Second cas
Ta structure A a été modifiée et contient maintenant l'ensemble de tes structures B qui se suivent en mémoire. Elle est maintenant bien plus lourde à gérer.
A chaque fois que tu fais "A.B[i]" le compilo doit décaler non pas de "i * sizeof(adresse)" octets mais "i * sizeof(B)" octets. Plus de calcul => plus de temps...
 
 
Je pense que si tu regardes comment est fait l'inode, tu auras déjà un bon point de repère.
 
 
T'as gagné. A une époque on gagnait du temps de calcul sur les tableaux de structures en les taillant à une taille pile poil puissance de 2 (256, 512, 1024, 2048, etc) car cela tombait sur des mots mémoires et l'optimiseurs pouvait décaler plus rapidement mais je ne sais pas si c'est encore utile aujourd'hui. Tu peux essayer de générer l'assembleur pour chaqu'un de tes 2 cas et voir la taille du source généré. C'est un bon point de repère. Mais je pense que le tableau d'adresses est encore ce qu'il y a de plus rapide.


 
OK on pense la meme chose ...
Merci pour ta réponse ...
 

n°1300670
julien_54
Posté le 07-02-2006 à 17:35:05  profilanswer
 

oups je me suis loupé pour la réponse précedente (certaines de mes remarques sont mélangées avec le texte de la réponse ...)


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Probleme d'indirection sur structures

 

Sujets relatifs
[PHP] mail avec pieces jointes ! probleme avec Lotus Notes [RESOLUT]Problème d'alignement avec IE (très bizarre) Code Inside
probleme images reactives sous IEProblème pour un code sous VBnet
pfffff probleme avec un menu en js[MySQL] problème avec la clause IN
[MySQL] Problème d'indexation FullTextprobléme de popup !!
php problème de datepetit probleme javascript
Plus de sujets relatifs à : Probleme d'indirection sur structures


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)