Processeur vectoriel
Un processeur vectoriel est un processeur possĂ©dant diverses fonctionnalitĂ©s architecturales lui permettant d'amĂ©liorer lâexĂ©cution de programmes utilisant massivement des tableaux, des matrices, et qui permet de profiter du parallĂ©lisme inhĂ©rent Ă l'usage de ces derniers.
DĂ©veloppĂ© pour des applications scientifiques et exploitĂ© par les machines Cray et les supercalculateurs qui lui feront suite, ce type d'architecture a rapidement montrĂ© ses avantages pour des applications grand public (on peut citer la manipulation d'images). Elle est implĂ©mentĂ©e en partie dans les processeurs grand public par des instructions SIMD, soit grĂące Ă une unitĂ© de calcul vectoriel dĂ©diĂ©e (AltiVec), soit simulĂ©e par des instructions bas niveau de type vectoriel (MMX/SSE). Contrairement au SIMD de type MMX, oĂč il faut charger les vecteurs dans les registres en plusieurs opĂ©rations puis exĂ©cuter une opĂ©ration supplĂ©mentaire sur ses registres, dans une unitĂ© vectorielle on charge l'adresse d'une table de vecteurs, la largeur des vecteurs ou du pas et la longueur de la table Ă traiter par instruction dans un registre, l'instruction vectorielle enchaĂźne ensuite son calcul sur l'ensemble des vecteurs de cette table.
Jeu d'instruction
Les processeurs vectoriels peuvent ĂȘtre vus comme des processeurs normaux, auxquels on a ajoutĂ© un certain nombre d'instructions optimisĂ©es pour la gestion des tableaux. Ces instructions optimisĂ©es pour les tableaux peuvent ĂȘtre vues comme des variantes d'instructions normales, mais optimisĂ©es pour traiter de plus grandes donnĂ©es (pour les accĂšs mĂ©moires), ou capables d'effectuer des opĂ©rations en parallĂšle. Ces instructions sont appelĂ©es des instructions vectorielles. Il en existe plusieurs types, qu'on va prĂ©senter dans ce qui suit.
Instructions de calcul vectoriel
Les instructions vectorielles sont des instructions qui effectuent plusieurs opĂ©rations en parallĂšle, sur des donnĂ©es diffĂ©rentes. Ces instructions de calcul vectoriel travaillent sur un ensemble de donnĂ©es de mĂȘme taille et de mĂȘme type, l'ensemble formant ce qu'on appelle un vecteur. Habituellement, ces vecteurs contiennent plusieurs nombres entiers ou nombres flottants placĂ©s les uns Ă cĂŽtĂ© des autres. Une instruction de calcul vectoriel va traiter chaque donnĂ©e du vecteur en parallĂšle, Ă savoir en mĂȘme temps et indĂ©pendamment des autres. Par exemple, une instruction d'addition vectorielle va additionner ensemble les donnĂ©es qui sont Ă la mĂȘme place dans deux vecteurs, et placer le rĂ©sultat dans un autre vecteur, Ă la mĂȘme place. Quand on exĂ©cute une instruction sur un vecteur, les donnĂ©es prĂ©sentes dans ce vecteur sont traitĂ©es simultanĂ©ment.
Les opĂ©rations en question peuvent ĂȘtre :
- des opérations bit à bit, comme des ET, OU, NOT bitwise ;
- des additions ;
- des soustractions ;
- des multiplications ;
- Ă©ventuellement des divisions ;
- ou des opérations mathématiques plus complexes.
Certaines instructions similaires sont disponibles sur certains processeurs non vectoriels. Par exemple, tous les processeurs x86 modernes contiennent des extensions Ă leur jeu d'instruction, comme le MMX ou le SSE, qui fournissent de telles instructions de calcul vectoriel.
Instructions d'accÚs mémoire
Tout processeur vectoriel possÚde des instructions d'accÚs mémoire diverses, dont au moins une instruction de lecture de vecteurs et une autre pour l'écriture. Sur les anciens processeurs vectoriels, les vecteurs sont lus ou écrits directement en mémoire. Un tel processeur vectoriel est qualifié de mémoire-mémoire. Cette appellation souligne le fait que les vecteurs sont lus et écrits directement dans la mémoire RAM de l'ordinateur, sans stockage intermédiaire visible dans le jeu d'instruction. Mais ce mode de fonctionnement pose quelques problÚmes de performances, compte tenu de la lenteur des accÚs mémoire et de l'inutilité des caches sur ce genre d'architecture. Les processeurs vectoriels de type Load-Store ont été inventés pour résoudre ce problÚme. Ceux-ci possÚdent des registres vectoriels, qui permettent de stocker des vecteurs dans leur intégralité. Un programmeur peut décider de placer certains vecteurs dans ces registres : les résultats intermédiaires de calculs sont enregistrés et accédés depuis ces registres, ce qui est plus rapide que d'aller les enregistrer et les manipuler en mémoire RAM. Pour utiliser ces registres vectoriels efficacement, le processeur doit pouvoir échanger des vecteurs entre la mémoire RAM et ces registres.
Les processeurs vectoriels load-store disposent d'instructions capables de transfĂ©rer des vecteurs entre la RAM et les registres vectoriels. Ces instructions sont des instructions d'accĂšs mĂ©moire. Sur les processeurs vectoriels, seules ces instructions peuvent aller lire ou Ă©crire en mĂ©moire : toutes les autres instructions vectorielles manipulent des vecteurs placĂ©s dans des registres vectoriels. Ces instructions ont des modes d'adressages spĂ©cialisĂ©s, de par la nature mĂȘme des vecteurs. Le mode d'adressage principal est le mode d'adressage absolu, Ă savoir que l'adresse du vecteur manipulĂ© est intĂ©grĂ©e directement dans le code machine de l'instruction, mais d'autres modes d'adressage inspirĂ©s des modes d'adressages sur architectures non-vectorielles sont aussi disponibles.
AccÚs mémoires contigus
Avec le mode d'adressage absolu, les instructions peuvent prĂ©ciser l'adresse mĂ©moire d'un vecteur, qui n'est alors qu'un paquet de donnĂ©es contigĂŒes en mĂ©moire. Par exemple, si le processeur manipule des vecteurs de 8 octets, chaque instruction d'accĂšs mĂ©moire utilisant le mode d'adressage absolu va lire ou Ă©crire dans des blocs de 8 octets. L'adresse de dĂ©part de ces blocs n'est soumise Ă aucune contrainte d'alignement, ce qui n'est pas le cas sur les processeurs modernes utilisant des jeux d'instructions comme le SSE, le MMX, etc. La raison Ă cela est que gĂ©rer des accĂšs non alignĂ©s en mĂ©moire rend les circuits de lecture/Ă©criture en mĂ©moire plus complexes. En contrepartie, ces contraintes compliquent l'utilisation des instructions vectorielles. Par exemple, un compilateur aura plus de mal Ă utiliser des instructions de calcul vectorielles en prĂ©sence de contraintes d'alignement.
AccĂšs en stride et en Scatter-Gather
Sur un processeur vectoriel, d'autres modes de chargements et d'enregistrement des vecteurs sont disponibles. On peut notamment citer l'existence d'accÚs mémoires en stride et en scatter-gather. Ces accÚs permettent à une instruction de charger des données dispersées en mémoire pour les rassembler dans un vecteur.
L'accĂšs en stride permet de charger ou d'enregistrer les donnĂ©es d'un vecteur qui sont sĂ©parĂ©es par un intervalle rĂ©gulier d'adresses. Une instruction d'accĂšs mĂ©moire voulant utiliser ce mode d'accĂšs a besoin de connaitre l'adresse initiale, celle du premier Ă©lĂ©ment du vecteur, et la distance entre deux donnĂ©es en mĂ©moire. Ce mode d'accĂšs permet aux instructions de mieux gĂ©rer les tableaux de structures, ainsi que les tableaux multi-dimensionnels. Lorsqu'on utilise de tels tableaux, il arrive aussi assez souvent que l'on n'accĂšde qu'Ă certains Ă©lĂ©ments tous sĂ©parĂ©s par une mĂȘme distance. Par exemple, si on fait des calculs de gĂ©omĂ©trie dans l'espace, on peut trĂšs bien ne vouloir traiter que les coordonnĂ©es sur l'axe des x, sans accĂšs sur l'axe des y ou des z. Les instructions d'accĂšs mĂ©moire en stride permettent au processeur de gĂ©rer de tels cas efficacement.
Dernier type d'accĂšs : le Scatter-Gather. Cet accĂšs sert Ă mieux gĂ©rer les matrices creuses. Dans ces matrices, une grande partie des Ă©lĂ©ments sont nuls. Dans un souci d'optimisation, seuls les Ă©lĂ©ments non nuls de la matrice sont stockĂ©s en mĂ©moire. Avec ce genre d'organisation, les instructions vectorielles ne seraient pas utilisables sur ce genre de matrices, sans Scatter-Gather. Les accĂšs en Scatter-Gather peuvent ĂȘtre vus comme une gĂ©nĂ©ralisation de l'adressage indirect Ă registre aux vecteurs. Avec cet accĂšs, les adresses de chaque Ă©lĂ©ment du vecteur sont stockĂ©es dans un registre vectoriel. L'accĂšs en Scatter-Gather va permettre d'aller lire ou Ă©crire aux diverses adresses rassemblĂ©es dans ce vecteur.
Registres des processeurs vectoriels
Comme dĂ©crit plus haut, sur certains processeurs, les vecteurs sont stockĂ©s dans des registres vectoriels pour plus dâefficacitĂ©. Ces registres ont tous une taille fixe. Ces registres ont une taille qui varie entre 64 et 256 bits, pour les tailles les plus courantes.
GĂ©nĂ©ralement, ces registres ne sont pas spĂ©cialisĂ©s : ils peuvent stocker indiffĂ©remment des entiers et des flottants. Et leur contenu sâadapte suivant leur taille. C'est-Ă -dire qu'un registre de 128 bits pourra stocker indiffĂ©remment :
- 8 entiers 16 bits ;
- 8 flottants 16 bits ;
- 4 entiers de 32 bits ;
- 4 flottants de 32 bits ;
- 2 entiers de 64 bits ;
- 2 flottants de 64 bits ;
- etc.
Un processeur vectoriel peut aussi incorporer d'autres registres pour faciliter le traitement des diverses instructions. Ces registres vont permettre au compilateur de mieux utiliser les instructions vectorielles pour compiler certaines structures logicielles. Parmi ces registres, on peut citer le Vector Length Register, et le Vector Mask Register.
Vectorisation
L'utilisation des instructions vectorielles permet de faciliter certains traitements sur les tableaux. De nos jours, ces instructions sont difficilement utilisables dans des langages de haut niveau, et c'est au compilateur de traduire certains traitements sur les tableaux en instructions vectorielles. Ces transformations permettant de traduire des morceaux de programmes en instructions vectorielles s'appelle la vectorisation.
DĂ©roulage de boucles
La transformation la plus basique est ce qu'on appelle le dĂ©roulage de boucles. Il s'agit d'une optimisation qui vise Ă rĂ©duire le nombre d'itĂ©rations d'une boucle en dupliquant son corps en plusieurs exemplaires. Elle est utilisĂ©e pour rĂ©duire le cout dâexĂ©cution des branchements et des autres opĂ©rations de comparaison de la boucle. Sur les processeurs SIMD, elle peut s'utiliser afin de rĂ©duire le temps dâexĂ©cution de boucles qui agissent sur des tableaux. D'ordinaire, les programmeurs utilisent une boucle pour rĂ©pĂ©ter un traitement sur tous les Ă©lĂ©ments d'un tableau, la boucle traitant un Ă©lĂ©ment Ă la fois. Nos instructions vectorielles permettent de traiter plusieurs Ă©lĂ©ments Ă la fois, ce qui fait que plusieurs tours de boucles peuvent ĂȘtre rassemblĂ©s en une seule instruction SIMD. Mais cela ne fonctionne que si les Ă©lĂ©ments du tableau sont traitĂ©s indĂ©pendamment, ou d'une façon assez simple, auquel cas la boucle peut ĂȘtre vectorisĂ©e. Pour cela, le compilateur va rĂ©pliquer le corps de la boucle (les instructions Ă rĂ©pĂ©ter) en plusieurs exemplaires dans cette boucle.
Exemple, prenons cette boucle, Ă©crite dans le langage C :
int i;
for (i = 0; i < 100; ++i)
{
a[i] = b[i] * 7 ;
}
Celle-ci peut ĂȘtre dĂ©roulĂ©e comme suit :
int i;
for (i = 0; i < 100; i+=4)
{
a[i] = b[i] * 7 ;
a[i+1] = b[i+1] * 7 ;
a[i+2] = b[i+2] * 7 ;
a[i+3] = b[i+3] * 7 ;
}
Si le compilateur rĂ©plique ces instructions en autant de fois qu'une instruction peut traiter dâĂ©lĂ©ments simultanĂ©ment, vectoriser la boucle devient trivial. Dans notre exemple, si jamais le processeur dispose d'une instruction de multiplication capable de traiter 4 Ă©lĂ©ments du tableau a ou b en une seule fois, la boucle dĂ©roulĂ©e peut ĂȘtre vectorisĂ©e assez simplement.
Strip mining
Le dĂ©roulage de boucles n'est toutefois pas une optimisation qui est valable pour toutes les boucles. Reprenons l'exemple de la boucle vue plus haut. Si jamais le tableau Ă manipuler a un nombre dâĂ©lĂ©ments qui n'est pas multiple de 4, la boucle ne pourra pas ĂȘtre vectorisĂ©e, les instructions de multiplication ne pouvant traiter que 4 Ă©lĂ©ments Ă la fois. Pour ce faire, les compilateurs utilisent gĂ©nĂ©ralement deux boucles : une qui traite les Ă©lĂ©ments du tableau avec des instructions SIMD, et une autre qui traite les Ă©lĂ©ments restants avec des instructions non vectorielles. Cette transformation s'appelle le strip-mining.
Par exemple, si on veut parcourir un tableau de taille fixe contenant 102 Ă©lĂ©ments, la boucle devra ĂȘtre dĂ©crite comme ceci :
int i;
for (i = 0; i < 100; i+=4)
{
a[i] = b[i] * 7 ;
a[i+1] = b[i+1] * 7 ;
a[i+2] = b[i+2] * 7 ;
a[i+3] = b[i+3] * 7 ;
}
for (i = 100; i < 102; ++i)
{
a[i] = b[i] * 7 ;
}
Mais les processeurs vectoriels contiennent des registres pour faciliter le traitement de ce genre de situation. Ils contiennent notamment un Vector Length Register, qui stocke le nombre dâĂ©lĂ©ments que notre instruction doit traiter. Avec ce registre, il est possible de demander Ă nos instructions vectorielles de ne traiter que les n premiers Ă©lĂ©ments d'un vecteur : il suffit de placer la valeur n dans ce registre. Ăvidemment, n doit ĂȘtre infĂ©rieur ou Ă©gal au nombre dâĂ©lĂ©ments maximal du vecteur. Avec ce registre, on n'a pas besoin d'une seconde boucle pour traiter les Ă©lĂ©ments restants, et une simple instruction vectorielle peut suffire.
Branchements
Autre obstacle Ă la vectorisation : la prĂ©sence de branchements conditionnels dans les boucles Ă vectoriser. Si une boucle contient des branchements conditionnels, il se peut que certaines instructions doivent ĂȘtre appliquĂ©es Ă certains Ă©lĂ©ments et pas Ă d'autres. Pour permettre aux compilateurs de dĂ©rouler ces boucles contenant des branchements, les processeurs vectoriels incorporent des techniques dans leur jeu dâinstructions.
On peut notamment citer le Vector Mask Register, qui permet d'implĂ©menter la prĂ©diction de certaines instructions vectorielles. Celui-ci permet de stocker des informations qui permettront de sĂ©lectionner certaines donnĂ©es et pas d'autres pour faire le calcul. Ce Vector Mask Register va stocker un bit pour chaque Ă©lĂ©ment du vecteur Ă traiter. Si ce bit est Ă 1, l'instruction doit sâexĂ©cuter sur la donnĂ©e associĂ©e Ă ce bit. Sinon, l'instruction ne doit pas la modifier. On peut ainsi traiter seulement une partie des registres stockant des vecteurs SIMD.
Micro-architecture
Un processeur vectoriel est composé de plusieurs éléments. Comme tous les processeurs, il contient notamment des registres, des unités de calcul, un séquenceur, et d'autres circuits pour accéder à la mémoire. Tout processeur normal contient des registres et des unités de calcul qui travaillent sur des nombres normaux. Un processeur vectoriel en possÚde aussi.
Toutefois, un processeur vectoriel va posséder des circuits en plus. Il faut notamment des registres vectoriels, comme vu plus haut. Mais un processeur vectoriel dispose aussi d'une ou de plusieurs unité(s) de calcul spécialisées dans le traitement des vecteurs. De plus, le processeur vectoriel contient aussi un circuit chargé de gérer les échanges de données entre mémoire et registres vectoriels : c'est ce circuit qui gÚre les instructions d'accÚs mémoire.
Caches
Les processeurs vectoriels peuvent disposer de mémoires caches. Des mémoires caches d'instruction sont assez courantes. Par contre, les mémoires caches de données sont souvent plus rares sur ce genre de processeur. Cela vient-il du fait que la localité temporelle des programmes utilisant des tableaux est faible ? De plus, les registres vectoriels sont souvent plus longs que les lignes de mémoire cache. Dans ces conditions, passer par une mémoire cache intermédiaire est inutile : autant passer directement par les registres vectoriels. Ainsi, les processeurs vectoriels disposent rarement de mémoires caches, et s'ils en utilisent, celles-ci sont spéciales (elles peuvent gérer un grand nombre de cache mis en attente simultanément).
Qui plus est, sur les processeurs vectoriels disposant de mémoires caches, ces mémoires caches sont souvent utilisées uniquement pour les échanges de données entre mémoire et registres non vectoriels. Les autres échanges ne passent pas par le cache.
AccÚs mémoires
Comme vu plus haut, les processeurs vectoriels ont besoin de charger ou d'enregistrer des vecteurs complets en mémoire. Nos processeurs ont donc besoin d'une mémoire qui possÚde un débit binaire assez élevé. Pour cela, un processeur vectoriel est souvent relié à une mémoire composée de plusieurs bancs mémoire.
Chacun de ces bancs mĂ©moire peut ĂȘtre vu comme une sorte de sous-mĂ©moire. Chacun de ces bancs mĂ©moires peut ĂȘtre accĂ©dĂ© en parallĂšle des autres. Ainsi, une lecture ou Ă©criture de vecteur peut ĂȘtre dĂ©composĂ©e en plusieurs lectures/Ă©critures, rĂ©parties sur plusieurs bancs. Ce qui est plus rapide que dâaccĂ©der Ă une seule mĂ©moire en sĂ©rie.
Pour que cette technique fonctionne, les adresses utilisĂ©es par notre programme doivent ĂȘtre rĂ©parties sur les diffĂ©rents bancs d'une certaine façon. Il faut que des adresses proches les unes des autres soient rĂ©parties dans des bancs diffĂ©rents. Dans le cas le plus simple, des adresses consĂ©cutives correspondront Ă des bancs consĂ©cutifs. Ainsi, si je dispose de N bancs, l'adresse A sera placĂ©e dans le banc 1, l'adresse A + 1 dans le banc 2⊠et l'adresse A + N dans le banc N. Une mĂ©moire organisĂ©e comme ceci s'appelle une mĂ©moire "interleaved" (entrelacĂ©e). Ces mĂ©moires gĂšrent mal les accĂšs en stride, aussi des organisations plus complexes sont souvent utilisĂ©es.
Unité de calcul vectorielle
Contrairement aux processeurs scalaires, les processeurs vectoriels sont spĂ©cialement conçus et optimisĂ©s pour exĂ©cuter la mĂȘme instruction sur chacune des donnĂ©es contenues dans un tableau. Ils sont surtout utilisĂ©s pour le calcul intensif sur supercalculateur.
LâexĂ©cution d'une opĂ©ration par l'unitĂ© de calcul est pipelinĂ©e. Par pipelinĂ©e, on veut dire que lâexĂ©cution de chaque instruction sera dĂ©coupĂ©e en plusieurs Ă©tapes, indĂ©pendantes les unes des autres. Cela ressemble un peu au fonctionnement d'une chaĂźne de montage, dans laquelle on dĂ©coupe la fabrication d'un objet en plein de sous-Ă©tapes qu'on effectue les unes aprĂšs les autres dans des boxes diffĂ©rents.
Au lieu d'attendre que lâexĂ©cution d'une opĂ©ration sur une donnĂ©e soit terminĂ©e avant de passer Ă la suivante, on peut ainsi commencer le traitement d'une nouvelle donnĂ©e sans avoir Ă attendre que l'ancienne soit terminĂ©e. Cela permet ainsi dâexĂ©cuter plusieurs instructions simultanĂ©ment dans notre unitĂ© de calcul. Toutes ces instructions en cours de calcul sont alors dans des Ă©tapes diffĂ©rentes.
Quand une instruction de calcul vectorielle est effectuée par l'unité de calcul, celle-ci exécutera son opération sur chaque élément des vecteurs à traiter. Ces éléments commenceront leur exécution uns par uns, et verront leurs traitement se faire étape par étape.
Startup Time
Avec une unitĂ© de calcul pipelinĂ©e, il est possible dâexĂ©cuter un grand nombre d'opĂ©rations simultanĂ©es. Si une unitĂ© de calcul vectorielle est dĂ©coupĂ©e en N Ă©tages (N Ă©tapes), alors elle peut gĂ©rer N opĂ©rations simultanĂ©es, chacune dans une Ă©tape diffĂ©rente.
Mais ce nombre maximal d'opĂ©rations met un certain temps avant d'ĂȘtre atteint. Il faut que suffisamment dâĂ©lĂ©ment aient Ă©tĂ© chargĂ©s dans le pipeline. Tous les Ă©tages sont utilisĂ©s avec N Ă©lĂ©ments chargĂ©s dans le pipeline. Chacun de ces Ă©lĂ©ments Ă©tant chargĂ© dans le pipeline un par un, lâutilisation optimale du pipeline n'est atteinte que lorsque l'unitĂ© de calcul commence Ă traiter le N-Ăšme Ă©lĂ©ment de nos vecteurs.
Le mĂȘme phĂ©nomĂšne arrive vers la fin du traitement des vecteurs : ceux-ci n'ont plus assez dâĂ©lĂ©ments pour remplir les diffĂ©rents Ă©tages du pipeline : quand il reste moins d'Ă©lĂ©ments Ă traiter qu'il n'y a d'Ă©tages, l'utilisation du pipeline est alors sous-optimale.
Chaining
Cette technique du pipeline peut encore ĂȘtre amĂ©liorĂ©e dans certains cas particuliers. Imaginons que l'on ait trois vecteurs : A, B et C. Pour chaque Ă©lĂ©ment i de ces vecteurs, supposons que l'on souhaite effectuer le calcul Ai + ( Bi * Ci ). Le processeur ne disposant pas d'instruction permettant de faire en une fois ce calcul, le programmeur doit utiliser deux instructions vectorielles : une d'addition, et une autre de multiplication. On pourrait penser que l'on doit effectuer d'abord la multiplication des paquets B et C, stocker le rĂ©sultat dans un paquet temporaire et effectuer l'addition de ce tableau avec le paquet A.
Mais certains processeurs incorporent des optimisations qui permettent d'utiliser leur pipeline plus efficacement. Le processeur peut en effet fusionner ces deux instructions indĂ©pendantes et les traiter en interne comme s'il sâagissait d'une instruction unique. Au lieu d'effectuer la multiplication, puis l'addition sĂ©parĂ©ment pour chaque Ă©lĂ©ment du vecteur, il peut effectuer la multiplication et l'addition pour le premier Ă©lĂ©ment, puis continuer avec le second, etc. En gros, il fusionne plusieurs instructions vectorielles en une seule instruction vectorielle qui regroupe les deux. Ce principe est appelĂ© le Vector Chaining.
Dans un processeur vectoriel implĂ©mentant le Vector Chaining, les deux calculs fusionnĂ©s sont exĂ©cutĂ©s l'un aprĂšs lâautre pour chaque Ă©lĂ©ment. Le pipeline de l'unitĂ© de calcul doit ĂȘtre conçu de façon que le rĂ©sultat de chaque Ă©tape d'un calcul soit rĂ©utilisable au cycle dâhorloge suivant. Ce rĂ©sultat ne doit pas ĂȘtre enregistrĂ© dans un registre vectoriel avant d'ĂȘtre rĂ©utilisable.
Marques et modĂšles
Ces marques fabriquent, ou bien ont fabriqué, des ordinateurs basés sur, ou contenant, des processeurs vectoriels :
- Cray depuis le Cray 1
- NEC gamme SX
- Fujitsu, VP400, VP2000, VPP500
- Hitachi, S-820
- IBM, option vectorielle (VF, pour Vector Facility) du modÚle 3090 dénommé 3090/VF
- RISC-V (extension V)
- DEC, processeur vectoriel optionnel sur le modÚle 9000 dénommé 9000/440VP
- CDC STAR 100, ETA 10E, Cyber 205, Cyber 2000V
- Texas Instruments TI-ASC (Advanced Scientific Computer)
Certaines consoles de jeu sont équipées de processeurs vectoriels, comme le processeur vectoriel Cell conçu par IBM, Sony et Toshiba pour la PlayStation 3.
Ne sont pas des processeurs vectoriels mais des SIMD :
- AltiVec, le SIMD d'IBM et Motorola, utilisés sur différents processeurs PowerPC, dont les gammes G4 et G5 utilisés notamment sur des ordinateurs Apple dans les années 1990.
- Les différentes extensions SIMD des processeurs x86.
- LâEmotion Engine, conçu par Sony et Toshiba pour la playStation 2 comporte deux unitĂ©s appelĂ© VPU, mais qui fonctionnent comme des SIMD.
- NEON, le SIMD d'ARM.