Algorithme de tri externe
Un algorithme de tri est dit externe lorsqu'il permet de trier des entrĂ©es trop grandes pour ĂȘtre contenues en intĂ©gralitĂ© dans la mĂ©moire principale d'un ordinateur. En rĂšgle gĂ©nĂ©rale, la mĂ©moire principale est la mĂ©moire vive, et l'algorithme recourt donc Ă l'usage d'une mĂ©moire situĂ©e plus bas dans la hiĂ©rarchie mĂ©moire, comme un disque dur.
Recourir Ă la mĂ©moire externe permet d'arriver Ă trier des volumes de donnĂ©es plus importants mais induit de nouvelles difficultĂ©s, le temps d'accĂšs aux donnĂ©es Ă©tant beaucoup plus long. Aller chercher chaque valeur sur le disque lorsque l'on en a besoin serait trop lent ; en pratique, les approches qui fonctionnent travaillent successivement sur diffĂ©rentes parties des donnĂ©es chargĂ©es temporairement dans la mĂ©moire principale. Les algorithmes de tri externe sont donc typiquement des variantes du tri fusion, qui s'adapte bien Ă ces contraintes : l'entrĂ©e est divisĂ©e en sous-ensembles pouvant ĂȘtre chargĂ©s un Ă un en mĂ©moire, triĂ©s puis rĂ©Ă©crits dans des fichiers temporaires qui sont ensuite fusionnĂ©s.
Tri fusion
Idée de l'algorithme
Le tri fusion externe divise l'entrée en blocs de taille à tenir dans la mémoire principale, puis fusionne les différents blocs triés[1] - [2].
Supposons que nous souhaitons trier 9Gb de données en ne disposant que de 1Gb de mémoire vive. L'idée de l'algorithme est la suivante :
- Charger 1Gb de données en mémoire vive et le trier en utilisant un algorithme de tri classique.
- Ăcrire ces donnĂ©es triĂ©es dans un fichier disque temporaire.
- Répéter les deux premiÚres étapes pour le reste des données. L'entrée est de taille 9Gb, nous disposons donc de 9 fichiers triés de 1Gb chacun, que l'on cherche désormais à fusionner.
- Copier en mĂ©moire les premiers 100Mb (=0,1Gb) de chaque fichier triĂ©. Chaque zone de 100Mb peut ĂȘtre vue comme un tampon d'entrĂ©e. Il reste sur la mĂ©moire vive 1Gb-9*100Mb=100Mb libres, que nous utilisons comme tampon de sortie.
- Fusionner petit à petit les 9 entrées, et écrire le résultat sur le tampon de sortie. Lorsqu'un tampon d'entrée se vide, les 100Mb suivants du fichier correspondant y sont chargés. Lorsque le tampon de sortie est plein, son contenu est écrit sur le disque (il s'agit de la sortie finale de l'algorithme).
L'idée clé de l'algorithme réside dans l'étape 5. Puisque les fichiers de taille 1Gb ont été triés, il n'est pas nécessaire pour les fusionner de les lire simultanément en intégralité : la plus petite valeur de l'ensemble d'entrée est nécessairement la plus petite (donc premiÚre) valeur d'un des neuf fichiers temporaires.
Notons que tous les fichiers temporaires crĂ©Ă©s sont fusionnĂ©s lors d'une unique fusion. Si cette technique peut se rĂ©vĂ©ler optimale dans certains cas, elle n'est le plus souvent pas viable. En effet, pour une quantitĂ© de mĂ©moire vive fixĂ©e, plus la taille de l'entrĂ©e est grande, et plus le nombre de fichiers temporaires crĂ©Ă©s est important. Lors de la fusion, la mĂ©moire vive est divisĂ©e en autant de tampons et ceux-ci perdent toute leur utilitĂ©, le plus gros du temps Ă©tant alors passĂ© Ă copier des donnĂ©es entre les mĂ©moires principale et externe. De plus, la dĂ©cision de diviser la mĂ©moire vive en 10 tampons est totalement arbitraire ; d'autres valeurs pourraient ĂȘtre utilisĂ©es.
Généralisation
L'exemple ci-dessus pourrait ĂȘtre dĂ©signĂ© comme un algorithme de tri fusion externe Ă deux passages. Le premier passage consiste en le tri des neuf fichiers de 1Gb, et le second passage en leur fusion. Une maniĂšre de rĂ©soudre les difficultĂ©s Ă©voquĂ©es est d'effectuer une fusion en plusieurs passages.
Notons le nombre de passages, le nombre de tampons (entrées + sorties), chacun étant de taille , et la taille de l'entrée. Dans le cas d'exemple, nous avions un passage de tri et un passage de fusion, utilisant neuf tampons d'entrée et un de sortie, soit , , et . Lors de chaque passage de fusion, les fichiers temporaires produits lors du passage précédent sont fusionnés par groupes de et le résultat est écrit dans un nouveau fichier temporaire. Le nombre de fichiers temporaires réduit à chaque passage, et le dernier passage fusionne fichiers ou moins en un unique fichier qui correspond à la sortie de l'algorithme.
Ătude de la complexitĂ©
Lors du premier passage, les données sont triées par blocs de taille ; la notion de tampon n'est pas importante dans ce cas, correspondant à la taille totale de la mémoire principale disponible, qui est à ce moment utilisée comme elle le serait pour n'importe quel algorithme de tri classique. Le nombre de fichiers temporaires créés est donc . à chaque passage suivant, nous effectuons des fusions à entrées. Le nombre de passages nécessaires est donc donné par la relation :
Lors de chaque fusion, on effectue lectures ou écritures sur le disque. La complexité totale est donc donnée par :
Fusion
Lors d'une fusion Ă plus de deux entrĂ©es, il est nĂ©cessaire Ă chaque itĂ©ration de comparer toutes les diffĂ©rentes entrĂ©es entre elles. Pour Ă©viter d'effectuer un nombre trop grand de comparaisons, une solution est d'utiliser un arbre de sĂ©lection[3], c'est-Ă -dire un arbre binaire dont chaque nĆud interne est Ă©tiquetĂ© (dans notre cas) par la valeur du plus petit de ses fils. Les feuilles de l'arbre correspondent aux plus petits Ă©lĂ©ments de chaque entrĂ©e Ă comparer entre eux. L'insertion d'une nouvelle valeur, qui correspond Ă une simple mise Ă jour de l'arbre, s'effectue en comparaisons.
Implémentations optimisées
Jim Gray a créé un comparatif d'algorithmes de tri externes finement paramétrés et optimisés. Plusieurs techniques sont utilisées pour réduire le temps d'exécution.
- Utilisation du parallélisme.
- Plusieurs disques durs peuvent ĂȘtre utilisĂ©s en parallĂšle pour augmenter la vitesse totale de lecture et d'Ă©criture.
- Plusieurs threads peuvent ĂȘtre utilisĂ©s pour exploiter les possibilitĂ©s des microprocesseurs multi-cĆurs.
- Les programmes peuvent effectuer des entrĂ©es/sorties asynchrones, de telle sorte qu'une partie des donnĂ©es peut ĂȘtre fusionnĂ©e tandis que d'autres donnĂ©es sont lues ou Ă©crites sur disque.
- Il est possible d'utiliser une grappe d'ordinateurs mis en réseau. TritonSort[4] a par exemple été testé sur une grappe de 52 machines pour trier 100Tb de données.
- Réduire la durée des entrées/sorties.
- Utiliser plus de mémoire vive permet de limiter le nombre de passages.
- Les temps d'accĂšs peuvent ĂȘtre rĂ©duis en utilisant de la mĂ©moire externe rapide, comme la technologie SSD, que ce soit en intĂ©gralitĂ© ou de maniĂšre hybride avec des disques durs.
- Autres optimisations.
- Certains tris utilisent une variante du tri par base lors du premier passage : ils séparent les données en sous-ensembles en fonction du commencement des valeurs (c.f. tri par distribution).
- S'il s'agit de trier des données longues en utilisant des clés courtes, il est possible de réarranger les clés séparément des valeurs afin de réduire la taille des entrées/sorties.
Tris bande
Dans les débuts de l'informatique, lorsque le coût des mémoires de type disques ou tambours magnétiques était trÚs élevé, les algorithmes de tri pouvaient n'utiliser que la mémoire centrale et les dérouleurs de bandes magnétiques.
En l'absence de disque, il fallait au moins quatre dérouleurs de bandes pour pratiquer un tel tri. Avec 4 dérouleurs (b1, b2, b3, b4), les opérations étaient les suivantes :
- montage (manuel) du fichier Ă trier sur le dĂ©rouleur b1, et de bandes de manĆuvre sur b2, b3, b4 ;
- lecture de b1 par paquets successifs qui sont triés en mémoire, pour générer des monotonies qui sont écrites en alternance sur les dérouleurs b3 et b4 ;
- sur le dĂ©rouleur b1, dĂ©montage de la bande contenant le fichier initial pour le remplacer par une bande de manĆuvre ;
- fusion (interclassement) des bandes b3 et b4 pour générer en alternance sur b1 et b2 des monotonies dont le volume est doublé ;
- fusion de b1 et b2 sur b3 b4, et itération de (4) et (5) jusqu'à ce que les monotonies atteignent 50 % du volume à trier ;
- fusion finale pour générer le résultat.
En pratique, compte tenu de la fiabilité moyenne des équipements, on rencontrait donc fréquemment des salles machines avec huit dérouleurs de bandes.
Tri par distribution
Les tris par distribution distibuent les entrĂ©es en sous-ensembles de plus petites tailles en fonction de leurs valeurs (typiquement, on effectue une partition de l'ensemble des Ă©lĂ©ments Ă trier). Ils s'adaptent Ă©galement Ă l'utilisation de mĂ©moire externe, les sous-ensembles pouvant ĂȘtre Ă©crits en diffĂ©rents fichiers. La principale difficultĂ© de ces algorithmes est de trouver la partition utilisĂ©e pour la distribution[5].
Annexes
Notes et références
- (en) Donald Knuth, The Art of Computer Programming : Sorting and searching, vol. Volume 3: Sorting and Searching, Addison-Wesley, , 2e Ă©d., 780 p. (ISBN 978-0-201-89685-5), p. 248â379
- (en) Ellis Horowitz et Sartaj Sahni, Fundamentals of Data Structures, H. Freeman & Co. (ISBN 978-0-7167-8042-7)
- « Les méthodes de tri externe »
- (en) Rasmussen, Alexander, Porter, George, Conley, Michael, Madhyastha, Harsha V, Mysore, Radhika Niranjan, Pucher, Alexander et Vahdat, Amin, « TritonSort: A Balanced Large-Scale Sorting System. », NSDI,â (lire en ligne)
- (en) J. S. Vitter, Algorithms and Data Structures for External Memory, now Publishers, , 174 p. (ISBN 978-1-60198-106-6, lire en ligne), p. 31-38
- (en) Cet article est partiellement ou en totalitĂ© issu de lâarticle de WikipĂ©dia en anglais intitulĂ© « External sorting » (voir la liste des auteurs).