Stockage d'arbre binaire

Stockage d'arbre binaire - C++ - Programmation

Marsh Posté le 29-09-2006 à 16:55:49    

Bonjour,
 
Je me pose la question de savoir quelle est la meilleure facon de stocker un arbre binaire.
Pour l'instant je stocke les fils gauches et droits de chaque noeud sous forme de pointeurs mais je me demandais si il n'existait pas de meilleure facon de faire (par exemple un tableau/vector de taille fixe alloué au depart avec les fils designés par indice).
 
L'arbre peut contenir plusieurs millions de noeuds mais est de taille fixe (je push mes noeuds dans un vector et quand j'ai fini je créé mon abre et je l'equilibre).
Le point critique au niveau temps doit etre le parcours de l'arbre.
 
La taille occupée en mémoire est aussi à prendre en compte.
 
 
Merci d'avance pour vos reponses.


Message édité par ArthurDent le 29-09-2006 à 19:48:32
Reply

Marsh Posté le 29-09-2006 à 16:55:49   

Reply

Marsh Posté le 29-09-2006 à 20:15:49    

Si tu as un tas, alors une structure tabulaire ça le fait.
Si ton arbre est grand : fais en sorte qu'il soit équilibré. Utilise un allocateur mémoire ne pas fragmenter ta mémoire comme un porc, tu y gagneras et en conso et mémoire et en temps de parcours.

Reply

Marsh Posté le 29-09-2006 à 21:30:14    

Taz a écrit :

Si tu as un tas, alors une structure tabulaire ça le fait.
Si ton arbre est grand : fais en sorte qu'il soit équilibré. Utilise un allocateur mémoire ne pas fragmenter ta mémoire comme un porc, tu y gagneras et en conso et mémoire et en temps de parcours.


 
l'arbre est en effet equilibré, mais n' pas une structure de tas. C'est en fait un kdtree, chaque noeud represente un plan de partitionnement  de l'espace, les noeuds de chaque sous arbre se situant de chaque coté de ce plan.
 
Donc tu me conseille plutot un vector avec la taille reservé au depart?

Reply

Marsh Posté le 29-09-2006 à 23:11:27    

non je n'ai pas dit ça. je te conseille un vrai allocateur mémoire pour allouer chaque noeud efficacement (et pas avec un new). Si ton arbre est équilibré et figé, à ce moment là, tu peux envisager un stockage tabulaire.

Reply

Marsh Posté le 30-09-2006 à 10:32:29    

Taz a écrit :

non je n'ai pas dit ça. je te conseille un vrai allocateur mémoire pour allouer chaque noeud efficacement (et pas avec un new). Si ton arbre est équilibré et figé, à ce moment là, tu peux envisager un stockage tabulaire.


 
ok merci, je vais donc commencer par garder la meme structure mais avec un allocateur et essayer ensuite en tabulaire et faire des tests de performance.

Reply

Marsh Posté le 10-10-2006 à 08:55:38    

La requête étant un peu floue, je vais m'en tenir à des généralités.
 
Il est assez facile de tasser les noeuds - feuille ou interne - d'un tel kD-tree en 8 octets, et si on est attentif celà se fait sans pénalité d'accès.

Code :
  1. struct node_t {
  2. struct {
  3.  uint32_t axis : 3; // extraction rapide de l'axe avec un et logique
  4.  uint32_t offset : 32-3-1; // pas besoin de decaler pour calculer l'adresse
  5.  uint32_t leaf : 1; // test simple (signe)
  6. };
  7. union {
  8.  float split;
  9.  uint32_t count;
  10. };
  11. };


L'usage de "déplacement" résoud plusieurs problèmes épineux (64bits etc...) et ce sans surcoût au parcours si on est sioux.
 
Généralement on a interêt à au moins allouer les noeuds par paire, c.a.d. que gauche & droite sont tjs contigus; celà amène des simplifications quand on traverse (notament pour le calcul d'adresse), une meilleur coherence etc...
 
Après, et selon les usages, il est possible de descendre à 4 octets, de placer les noeuds de façon à optimiser la cachabilité et autres finasseries. Les variations sont sans fins :)
 
Tjs est-il que sous cette forme on peut directement mmapper l'arbre ou le reloger (ce qui permet de "streamer" à la création + mmap derriere).
 
EDIT: j'ai oublié de préciser que celà supose un alignement idoine.


Message édité par tbp le 10-10-2006 à 09:37:47
Reply

Marsh Posté le 16-10-2006 à 16:10:31    

c'est certain, mais si ton bute est de mmaper pour un dump binaire directe, je pense qu'il est vraiment plus clair et plus simple de travailler avec une structure tabulaire plutot que de se reposer sur un allocateur mémoire pour ça. L'inconvénient c'est effectivement que si ton arbre n'est pas très équilibré, tu gaches beaucoup de mémoire. Cela dit, tu pourrais presque envisager d'utiliser des index plutot que des pointeurs, et à ce moment là, tu travailler dans un tableau de manière quasi-transparente. Tu maintiens une liste des noeuds libres pour pas scanner tout pour trouver une case de libre et voilà. Ça doit pouvoir fonctionner, à voir en termes de performances.

Reply

Marsh Posté le 16-10-2006 à 17:02:10    

Je suppose qu'ArthurDent utilise son kD-tree pour du photon mapping, vu qu'il l'équilibre dans une dernière passe; je l'utilise plutôt pour du partitionnement spatial, les chances pour qu'il soit équilibré sont presques nulles.
Dans ce cas de figure l'arbre lui même ne represente qu'une part négligeable de la mémoire nécessaire à la phase de construction. De même il facile d'amortir qques passes en "post-process", si besoin est.
 
La question initiale étant l'optimisation du temps de parcours, il n'en reste pas moins que dans la forme que j'ai présenté, si node est le noeud courant alors (node + (node->offset & ~8)) ^ (8 & celui_de_droite) est le fils voulu; il me faut moins de 20 cycles/noeud pour faire traverser 4 rayons pour peu que je touche la cache.  
Difficile de faire mieux, donc.  :)


Message édité par tbp le 16-10-2006 à 17:05:42
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed