Fonctionnement d'un ordinateur/Les architectures découplées

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche

Les processeurs actuels utilisent des optimisations relativement lourdes pour gagner en performances, qui utilisent beaucoup de circuits. Évidemment, les chercheurs ont déjà trouvé quelques alternatives : processeurs VLIW et EPIC, techniques d’exécution dans le désordre, etc. Mais il existe une dernière alternative, relativement mal connue : les architectures découplées. Il existe plusieurs architectures de ce type, que nous allons aborder via quelques exemples.

Découplage des accès mémoire[modifier | modifier le wikicode]

La première catégorie d'architectures découplées est celle des architectures découplées accès-exécution. Ces architectures ont un processeur dédié aux accès mémoires et un autre pour le reste. Le processeur en charge des accès mémoire s'appelle le processeur access, ou A. L'autre processeur, appelé execute, s'occupe des calculs et des branchements. Sur ces architectures, chaque programme est découpé en deux flux d'instructions : un pour les accès mémoire, et l'autre pour le reste. Les deux flux sont exécutés en parallèle, un flux pouvant prendre de l'avance sur l'autre. Ainsi, les lectures peuvent être exécutées en avance. Cette forme de parallélisme est certes plus limitée que celle permise par l’exécution dans le désordre, mais le principe est là. Le découpage du programme en plusieurs flux peut s'effectuer soit à l'exécution, soit à la compilation. Dans le premier cas, on n'utilise qu'un seul et unique programme, qui contient toutes les instructions. Ces processeurs disposent d'une unique unité de chargement, partagée entre les processeurs. Dans le second cas, chaque flux correspondra à un programme séparé. Chaque processeur a un program counter, même s'il y a une synchronisation pour les branchements.

Gestion des accès mémoire[modifier | modifier le wikicode]

Les accès mémoire sont gérés grâce à diverses mémoires FIFO, qui servent d'interface entre les processeurs et la mémoire. Prenons le cas d'une lecture : la lecture est démarrée par le processeur access, alors que la donnée est destinée au processeur execute. Pour synchroniser les deux processeurs, on trouve une mémoire tampon pour les données lues : la file de lecture de X (X load queue, abréviée XLQ). Quand le processeur X a besoin d'une donnée lue depuis la mémoire, il vérifie si elle est présente dans l'XLQ et se met en attente tant que ce n'est pas le cas.

Le cas des écritures est plus compliqué. En effet, l'adresse de l'écriture est calculée par le processeur A, tandis que la donnée à écrire est calculée par le processeur X, et les deux ne sont pas forcément disponibles en même temps. Pour cela, les adresses et les données sont mises en attente dans deux mémoires tampons qui coopèrent entre elles. La première est intégrée dans le processeur A et met en attente les adresses calculées : c'est la file d’écriture des adresses (store address queue, ou SAQ). La seconde met en attente les données à lire, et relie le processeur X au processeur A : c'est la file d’écriture de X (X store queue, ou XSQ). Quand l'adresse et la donnée sont disponibles en même temps, l'écriture est alors envoyée à la mémoire ou au cache.

Échanges d'information entre processeurs[modifier | modifier le wikicode]

Évidemment, les deux processeurs doivent échanger des informations. Par exemple, une donnée lue par le processeur A peut servir d'opérande pour des instructions sur le processeur X. De même, le calcul d'une adresse sur le processeur A peut utiliser des données calculées par le processeur X. Pour cela, les échanges s'effectuent par copies entre registres : un registre peut être copié du processeur A vers le processeur X, et réciproquement. Pour utiliser cette unité de copie, chaque processeur dispose d'une instruction COPY.

Branchements[modifier | modifier le wikicode]

Ces deux flux ont exactement la même organisation générale : les branchements sont présents à des endroits identiques dans les deux flux, les structures de contrôle présentes dans un programme sont présentes à l'identique dans l'autre, etc. Or, un branchement pris par un processeur doit être pris sur l'autre : le résultat d'un branchement sur un processeur doit être transmis à l'autre processeur. Pour cela, on trouve deux files d'attente :

  • la file A vers X (access-execute queue, abréviée AEQ), pour les transferts du processeur A vers le processeur X ;
  • la file X vers A (execute-access queue, abréviée EAQ), pour l'autre sens.

Il faut noter que le processeur peut se trouver définitivement bloqué dans une situation bien précise : si l'AEQ et l'EAQ sont toutes deux totalement remplies ou totalement vide, ce genre de situation peut survenir. Pour éviter cette situation, les compilateurs doivent compiler le code source d'une certaine manière.

Résumé d'une architecture découplée de type access-execute.

Découplage des branchements[modifier | modifier le wikicode]

L'idée qui consiste à séparer un programme en deux flux a été adaptée sous d'autres formes.

Découplage simple[modifier | modifier le wikicode]

Par exemple, on peut avoir un flux juste pour les branchements, à savoir calculer leurs adresses et les exécuter. Dans ce cas, on a toujours deux processeurs : un pour les branchements et un autre. L'architecture est fortement simplifié, une seule mémoire FIFO étant nécessaire : celle-ci permet au processeur généraliste d'envoyer des données au processeur qui gère les branchements.

Architecture découplée à découplage simple des branchements.

Découplage total du contrôle[modifier | modifier le wikicode]

Il est possible d'aller encore plus loin : l'article « The effectiveness of decoupling » donne une architecture qui découple accès mémoire, branchements et calculs. Cette architecture a été implémentée en matériel quelques années après la publication de l'article. On a donc trois processeurs :

  • un processeur maitre pour les branchements, qui répartit le travail à effectuer sur les deux autres processeurs ;
  • un processeur pour la mémoire ;
  • un processeur pour les calculs.
Architecture à découplage total du contrôle.

Les deux derniers processeurs ne peuvent qu'exécuter des boucles assez spéciales : ces boucles ne doivent pas contenir de branchements ou de boucles imbriquées à l'intérieur. Vu que le processeur maitre gère les autres branchements, les files d'attente dédiées aux branchements disparaissent. Le processeur maitre gère la répartition des boucles sur les deux autres processeurs. Pour demander l’exécution d'une boucle sur processeur, le processeur maître envoie ce qu'on appelle un bloc de chargement d’instructions (instruction fetch block ou IFB). Cet IFB contient un pointeur sur la première instruction de la boucle, le nombre d'instructions de la boucle et le nombre d'itérations. L'envoi d'un IFB sur les mémoires tampons est réalisé sur ordre d'une instruction machine spécialisée.

Autres[modifier | modifier le wikicode]

Si les accès mémoire et les branchements peuvent être découplés, la gestion du cache de données ou d'instructions peut aussi l'être. Comme exemple, on peut citer le hierarchical decoupled instruction stream computer : sur cette architecture, le cache n'est pas géré automatiquement par le matériel, mais l'est par des instructions machine. Pour indiquer quelles sont les données préchargées, le processeur de gestion du cache envoie des informations au processeur de gestion des accès mémoire, via une file d'attente.