« Fonctionnement d'un ordinateur/Les architectures dataflow » : différence entre les versions

Contenu supprimé Contenu ajouté
Aucun résumé des modifications
Ligne 75 :
[[Image:Dataflowmanchester.png|vignette|286px|right|Synoptique simplifié de la machine de l'Université de Manchester ([[1981]])]]
 
Pour résoudre les défauts des architectures ''dataflow'' statiques, il faut faire sauter la règle du "un jeton par flèche", ce qui est fait sur les '''architectures ''dataflow'' dynamiques'''. L'idée de ces architectures est d'associer, pour chaque jeton, l'exemplaire d'une fonction ou d'une boucle ils sont destinés. Pour cela, on ajoute des informations à cotécôté de l'opérande, regroupées dans ce qu'on appelle le ''tag''. Dorénavant, une instruction s’exécute une fois que tous ses opérandes ayant le même tag sont disponibles.
 
Sur les architectures statiques, les jetons avaient un emplacement pré-reservéréservé dans les instructions mêmes. Mais sur les architectures dynamiques, on ne peut réserver de la place pour les opérandes à l'avance, vu qu'une instruction dans une boucle ou une fonction peut s’exécuter en un nombre indéterminé d'exemplaires. C'est maintenant aux jetons d'indiquer quelle est l'instruction qui doit les manipuler, en mémorisant son adresse. Les opérandes sont mémorisés à part des instructions, dans une mémoire séparée de la mémoire d'instructions (en clair, les architectures dynamiques sont de type Harvard). Les opérandes sont mis en attente dans une file d'attente. À chaque ajout d'un opérande dans la file d'attente, le processeur vérifie quels sont les opérandes de la file qui possèdent le même tag et la même adresse d'instruction.
 
La gestion des jetons change du tout au tout. Les jetons contiennent l'opérande, leur ''tag'', et l'adresse de l'instruction de destination, ainsi que le nombre d'opérandes de cette instruction (afin de faciliter la détection de la disponibilité des opérandes de celle-ci). Dès qu'un jeton a été calculé par l'ALU, il est stocké dans la file d'attente des jetons disponibles. Reste à vérifier la disponibilité des opérandes. Si l'instruction a toutes ses opérandes disponibles dans cette file d'attente, il y a juste à les récupérer et à lancer l'instruction. Ainsi, à chaque ajout d'un jeton dans la file d'attente des jetons, on va vérifier quelles sont les jetons présents dans cette file qui possèdent le même Tag, afin de charger celle-ci le cas échéant.
Ligne 87 :
==Les architectures ''Explicit Token Store''==
 
Les '''architectures Explicit Token-Store''' utilisent une sorte de pile. L'opérande est remplacé par deux choses : un pointeur vers le cadre de pile qui contient la donnée et de quoi localiser l'opérande dans la pile. Elle représentent une amélioration assez conséquente des architectures précédentes. Sur ces machines, lorsqu’une fonction ou une boucle s’exécute, elle réserve un cadre de pile et y stocke ses opérandes et ses variables locales. A chaque appel d'une fonction ou à chaque itération d'une boucle, on crée un nouveau cadre pour les opérandes de la dite version. Ainsi, chaque fonction ou itération de boucle pourra avoir son propre jeu d'opérandes et de variables locales, permettant ainsi l'utilisation de fonctions réentrantesré-entrantes ou récursives et un déroulage matériel des boucles.
 
Ces cadres de pile sont localisés par leur adresse mémoire et les instructions ont juste à repérer la position dans le cadre de pile. La différence avec la pile des architectures usuelles tient dans le fait que les cadres de pile ne sont pas contiguës, mais peuvent être dispersées n'importe où et n'importe comment (ou presque) en mémoire. Qui plus est, les cadres de pile ne sont pas organisés avec une politique d'ajout et de retraits de type LIFO. Chaque donnée présente dans un cadre de pile possède des bits de présence, comme toutes les autres données.
Ligne 97 :
Les architectures dataflow sont certes très belles et créatives, mais celles-ci souffrent de défauts qui empêchent de les utiliser de façon réellement efficace.
 
Premièrement, la gestion des jetons et des instructions est compliquée et utilise beaucoup de circuits. La détection de la disponibilité des opérandes d'une instruction est assez couteusecoûteuse et prend un certain temps, vu qu'elle est faite avec des mémoires associatives. Hors, les mémoires associatives sont redoutablement lentes, ce qui pose de gros problèmes de performances. Le temps d'accès à la mémoire est suffisant pour compenser tous les gains apportés par la parallélisation. Autre problème : la répartition des instructions prêtes sur les différentes unités de calcul prend un certain temps, difficile à amortir. Autre problème : les tags prennent de la mémoire, suffisamment pour devenir un problème. Ensuite, l'immutabilité des variables fait que la gestion des structures de données est laborieuse pour le compilateur et le programmeur, entraineentraîne beaucoup d'allocations mémoires et augmente fortement le nombre de lectures et écritures en mémoire, comparé à un programme impératif.
 
Et ensuite, le plus gros problème de tous : ces architectures sont limitée par la rapidité de la mémoire RAM principale. La même chose a lieu dans les programmes impératifs sur des architectures normale, à la différence que celles-ci ont des caches et une hiérarchie mémoire, afin d'amortir le coutcoût des accès mémoires. Mais ces techniques ne fonctionnent correctement que lorsque le code exécuté a une bonne localité temporelle et spatiale. Ce qui n'est franchement pas le cas des programmes conçus pour les architectures ''dataflow'' et des programmes fonctionnels en général (à cause de l'immutabilité de variables, d'allocations mémoires fréquentes, des structures de donnée utilisées, etc).
 
On peut toujours compenser ces défauts en exécutant beaucoup d'instructions en parallèle, mais rares sont les programmes capables d’exécuter un grand nombre d'instructions à exécuter en parallèle. Il faut dire que les dépendances de données sont légion et qu'il n'y a pas de miracles. On ne peut pas toujours trouver suffisamment d'instructions à paralléliser, sauf dans certains programmes, qui résolvent des problèmes particuliers. En conséquence, les ''architectures dataflow'' ont étés abandonnées, après pas mal de recherches, en raison de leurs faibles performances. Mais certains chercheurs ont quand même décidés de donner une dernière chance au paradigme ''dataflow'', en le modifiant de façon à le rendre un peu plus impératif.
Ligne 109 :
===Les architecture ''Explicit Data Graph Execution''===
 
Les architectures '''''Explicit Data Graph Execution''''' se basent sur le fonctionnement des compilateurs modernes pour découper un programme procédural ou impératif en blocs de code. Généralement, ceux-ci vont découper un programme en petits morceaux de code qu'on appelle des blocs de base, qui sont souvent délimités par des branchements (ou des destinations de branchements). Ces sont ces blocs de base qui seront exécutés dans l'ordre des dépendances de données. Certaines architectures de ce type ont déjà été inventées, comme les processeurs ''WaveScalar'' et ''TRIPS''.
 
==Conclusion==
Ligne 117 :
* [http://csd.ijs.si/courses/dataflow/index.htm Dataflow Computers].
 
Quelques liens sur l'architecture ''wavescalar'' :
 
* [https://homes.cs.washington.edu/~oskin/wavescalar.pdf Wavescalar].