Ce sont deux phrases qui décrivent la même chose à partir de points de vue (très légèrement) différents. La programmation parallèle décrit la situation du point de vue du matériel - il y a au moins deux processeurs (éventuellement dans un seul package physique) travaillant sur un problème en parallèle. La programmation simultanée décrit davantage les choses du point de vue du logiciel - deux actions ou plus peuvent se produire exactement en même temps (simultanément).
Le problème ici est que les gens essaient d'utiliser les deux phrases pour faire une distinction claire lorsqu'aucune n'existe réellement. La réalité est que la ligne de démarcation qu'ils essaient de tracer est floue et indistincte depuis des décennies, et est devenue de plus en plus indistincte au fil du temps.
Ce qu'ils essaient de discuter, c'est le fait qu'il était une fois, la plupart des ordinateurs n'avaient qu'un seul processeur. Lorsque vous exécutiez plusieurs processus (ou threads) sur ce même processeur, celui-ci n'exécutait réellement qu'une instruction à partir de l'un de ces threads à la fois. L'apparition de la concurrence était une illusion - le processeur basculant entre l'exécution d'instructions à partir de différents threads assez rapidement pour que, selon la perception humaine (à quoi tout ce qui est inférieur à 100 ms environ semble instantané), il semblait qu'il faisait beaucoup de choses à la fois.
Le contraste évident avec cela est un ordinateur avec plusieurs processeurs ou un processeur avec plusieurs cœurs, de sorte que la machine exécute des instructions à partir de plusieurs threads et / ou processus en même temps; l'exécution de code ne peut / n'a aucun effet sur l'exécution de code dans l'autre.
Maintenant, le problème: une distinction aussi nette n'a presque jamais existé. Les concepteurs informatiques sont en fait assez intelligents, ils ont donc remarqué il y a longtemps que (par exemple) lorsque vous aviez besoin de lire des données à partir d'un périphérique d'E / S tel qu'un disque, cela prenait beaucoup de temps (en termes de cycles CPU) terminer. Au lieu de laisser le processeur inactif pendant ce temps, ils ont trouvé différentes façons de laisser un processus / thread effectuer une demande d'E / S et de laisser le code d'un autre processus / thread s'exécuter sur le processeur pendant que la demande d'E / S est terminée.
Ainsi, bien avant que les processeurs multicœurs ne deviennent la norme, nous avions des opérations à partir de plusieurs threads en parallèle.
Ce n'est que la pointe de l'iceberg. Il y a des décennies, les ordinateurs ont également commencé à fournir un autre niveau de parallélisme. Encore une fois, étant des gens assez intelligents, les concepteurs d'ordinateurs ont remarqué que dans de nombreux cas, ils avaient des instructions qui ne s'influencaient pas mutuellement, il était donc possible d'exécuter plus d'une instruction à partir du même flux en même temps. Un des premiers exemples qui est devenu assez connu était le Control Data 6600. C'était (avec une marge assez large) l'ordinateur le plus rapide au monde lorsqu'il a été introduit en 1964 - et une grande partie de la même architecture de base reste en usage aujourd'hui. Il suivait les ressources utilisées par chaque instruction et disposait d'un ensemble d'unités d'exécution qui exécutaient les instructions dès que les ressources dont elles dépendaient étaient disponibles, très similaires à la conception des processeurs Intel / AMD les plus récents.
Mais (comme le disaient les publicités), attendez - ce n'est pas tout. Il y a encore un autre élément de conception pour ajouter encore plus de confusion. Il a reçu plusieurs noms différents (par exemple, "Hyperthreading", "SMT", "CMP"), mais ils se réfèrent tous à la même idée de base: un processeur qui peut exécuter plusieurs threads simultanément, en utilisant une combinaison de certaines ressources qui sont indépendants pour chaque thread et certaines ressources partagées entre les threads. Dans un cas typique, cela est combiné avec le parallélisme au niveau de l'instruction décrit ci-dessus. Pour ce faire, nous avons deux (ou plus) ensembles de registres architecturaux. Ensuite, nous avons un ensemble d'unités d'exécution qui peuvent exécuter des instructions dès que les ressources nécessaires sont disponibles.
Ensuite, bien sûr, nous arrivons aux systèmes modernes avec plusieurs cœurs. Ici, les choses sont évidentes, non? Nous avons N (quelque part entre 2 et 256 environ pour le moment) des cœurs séparés, qui peuvent tous exécuter des instructions en même temps, nous avons donc un cas clair de parallélisme réel - l'exécution des instructions dans un processus / thread ne fonctionne pas '' t affecter l'exécution des instructions dans un autre.
Eh bien, en quelque sorte. Même ici, nous avons des ressources indépendantes (registres, unités d'exécution, au moins un niveau de cache) et des ressources partagées (généralement au moins le niveau de cache le plus bas, et certainement les contrôleurs de mémoire et la bande passante à la mémoire).
Pour résumer: les scénarios simples que les gens aiment comparer entre les ressources partagées et les ressources indépendantes ne se produisent pratiquement jamais dans la vie réelle. Avec toutes les ressources partagées, nous nous retrouvons avec quelque chose comme MS-DOS, où nous ne pouvons exécuter qu'un programme à la fois, et nous devons arrêter d'en exécuter un avant de pouvoir exécuter l'autre. Avec des ressources complètement indépendantes, nous avons N ordinateurs exécutant MS-DOS (sans même un réseau pour les connecter) sans possibilité de partager quoi que ce soit entre eux (car si nous pouvons même partager un fichier, eh bien, c'est une ressource partagée, un violation de la prémisse de base de ne rien partager).
Chaque cas intéressant implique une combinaison de ressources indépendantes et de ressources partagées. Chaque ordinateur raisonnablement moderne (et beaucoup qui ne sont pas du tout modernes) a au moins une certaine capacité d'effectuer au moins quelques opérations indépendantes simultanément, et à peu près tout ce qui est plus sophistiqué que MS-DOS en a profité au moins Un certain degré.
La division nette et nette entre "simultané" et "parallèle" que les gens aiment dessiner n'existe tout simplement pas, et presque jamais. Ce que les gens aiment classer comme "simultané" implique généralement toujours au moins un et souvent plusieurs types différents d'exécution parallèle. Ce qu'ils aiment classer comme «parallèle» implique souvent le partage de ressources et (par exemple) un processus bloquant l'exécution d'un autre tout en utilisant une ressource partagée entre les deux.
Les gens qui essaient de faire une distinction nette entre «parallèle» et «simultané» vivent dans un fantasme d'ordinateurs qui n'a jamais réellement existé.