Quelle est la différence entre une programmation simultanée et une programmation parallèle? J'ai demandé à Google, mais je n'ai rien trouvé qui m'a aidé à comprendre cette différence. Pourriez-vous me donner un exemple pour les deux?
Pour l'instant, j'ai trouvé cette explication: http://www.linux-mag.com/id/7411 - mais "la concurrence est une propriété du programme" vs "l'exécution parallèle est une propriété de la machine" ne me suffit pas - je ne peux toujours pas dire ce qui est quoi.
Réponses:
Si votre programme utilise des threads (programmation simultanée), il ne sera pas nécessairement exécuté comme tel (exécution parallèle), car cela dépend si la machine peut gérer plusieurs threads.
Voici un exemple visuel. Threads sur une machine non filetée :
Fils sur une machine filetée :
Les tirets représentent le code exécuté. Comme vous pouvez le voir, ils se séparent et s'exécutent séparément, mais la machine filetée peut exécuter plusieurs pièces distinctes à la fois.
la source
Programmation simultanéeconcerne les opérations qui semblent se chevaucher et se préoccupe principalement de la complexité qui résulte du flux de contrôle non déterministe. Les coûts quantitatifs associés aux programmes simultanés sont généralement à la fois le débit et la latence. Les programmes simultanés sont souvent liés aux E / S mais pas toujours, par exemple les récupérateurs de mémoire concurrents sont entièrement sur le processeur. L'exemple pédagogique d'un programme simultané est un robot d'exploration Web. Ce programme lance des demandes de pages Web et accepte les réponses simultanément lorsque les résultats des téléchargements deviennent disponibles, accumulant un ensemble de pages qui ont déjà été visitées. Le flux de contrôle n'est pas déterministe car les réponses ne sont pas nécessairement reçues dans le même ordre à chaque exécution du programme. Cette caractéristique peut rendre très difficile le débogage de programmes simultanés.Erlang , les flux de travail asynchrones F # et la bibliothèque Akka de Scala sont peut-être les approches les plus prometteuses pour une programmation hautement concurrente.
Programmation multicœurest un cas particulier de programmation parallèle. La programmation parallèle concerne les opérations qui se chevauchent dans le but spécifique d'améliorer le débit. Les difficultés de la programmation simultanée sont éludées en rendant le flux de contrôle déterministe. En règle générale, les programmes génèrent des ensembles de tâches enfants qui s'exécutent en parallèle et la tâche parent ne se poursuit qu'une fois chaque sous-tâche terminée. Cela rend les programmes parallèles beaucoup plus faciles à déboguer que les programmes simultanés. La partie difficile de la programmation parallèle est l'optimisation des performances en ce qui concerne des problèmes tels que la granularité et la communication. Ce dernier est toujours un problème dans le contexte des multicœurs car il y a un coût considérable associé au transfert de données d'un cache à un autre.Cilk est peut-être l'approche la plus prometteuse pour la programmation parallèle hautes performances sur multicœurs et elle a été adoptée à la fois dans les blocs de construction filetés d'Intel et dans la bibliothèque parallèle de tâches de Microsoft (dans .NET 4).
la source
https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html
Concurrent = Deux files d'attente et une machine à café.
Parallèle = Deux files d'attente et deux machines à café.
la source
Interpréter la question d'origine comme un calcul parallèle / simultané au lieu de la programmation .
Dans le calcul simultané, deux calculs avancent tous deux indépendamment l'un de l'autre. Le deuxième calcul n'a pas à attendre la fin du premier pour avancer. Il n'indique cependant pas le mécanisme permettant d'y parvenir. Dans une configuration monocœur, la suspension et l'alternance entre les threads sont requises (également appelées multithreading préventif ).
Dans le calcul parallèle, deux calculs avancent tous les deux simultanément - c'est-à-dire littéralement en même temps. Cela n'est pas possible avec un seul processeur et nécessite plutôt une configuration multicœur.
Images de l'article: "Parallèle vs Concurrent dans Node.js"
contre
la source
Dans la vue d'un processeur, il peut être décrit par cette photo
Dans la vue d'un processeur, il peut être décrit par cette photo
la source
Je crois que la programmation simultanée fait référence à la programmation multithread qui consiste à laisser votre programme exécuter plusieurs threads, abstrait des détails du matériel.
La programmation parallèle fait référence à la conception spécifique de vos algorithmes de programme pour tirer parti de l'exécution parallèle disponible. Par exemple, vous pouvez exécuter en parallèle deux branches de certains algorithmes en espérant qu'il atteindra le résultat plus tôt (en moyenne) que si vous vérifiiez d'abord la première puis la deuxième branche.
la source
J'ai trouvé ce contenu dans un blog. Je l'ai trouvé utile et pertinent.
La concurrence et le parallélisme ne sont PAS la même chose. Deux tâches T1 et T2 sont simultanées si l'ordre dans lequel les deux tâches sont exécutées dans le temps n'est pas prédéterminé,
T1 peut être exécuté et terminé avant T2, T2 peut être exécuté et terminé avant T1, T1 et T2 peuvent être exécutés simultanément en même temps (parallélisme), T1 et T2 peuvent être exécutés alternativement, ... Si deux threads simultanés sont planifiés par le système d'exploitation pour s'exécuter sur un seul processeur non SMT non CMP, vous pouvez obtenir la simultanéité mais pas le parallélisme. Le parallélisme est possible sur des systèmes multicœurs, multiprocesseurs ou distribués.
La concurrence est souvent désignée comme une propriété d'un programme et est un concept plus général que le parallélisme.
Source: https://blogs.oracle.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming
la source
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é.
la source
Source: PThreads Programming - Un standard POSIX pour un meilleur multitraitement, Buttlar, Farrell, Nichols
la source
Et
Pour comprendre la différence, je recommande fortement de voir cette vidéo de Rob Pike (l'un des créateurs de Golang). La concurrence n'est pas le parallélisme
la source
La programmation parallèle se produit lorsque le code est exécuté en même temps et que chaque exécution est indépendante de l'autre. Par conséquent, il n'y a généralement pas de préoccupation concernant les variables partagées et autres, car cela ne se produira probablement pas.
Cependant, la programmation simultanée consiste à exécuter du code par différents processus / threads qui partagent des variables et ainsi, par conséquent, à la programmation simultanée, nous devons établir une sorte de règle pour décider quel processus / thread s'exécute en premier, nous voulons cela afin d'être sûrs qu'il sera la cohérence et que nous pouvons savoir avec certitude ce qui va se passer. S'il n'y a pas de contrôle et que tous les threads calculent en même temps et stockent les choses sur les mêmes variables, comment saurions-nous à quoi s'attendre à la fin? Peut-être qu'un thread est plus rapide que l'autre, peut-être que l'un des threads s'est même arrêté au milieu de son exécution et qu'un autre a poursuivi un calcul différent avec une variable corrompue (pas encore entièrement calculée), les possibilités sont infinies. C'est dans ces situations que nous utilisons généralement la programmation simultanée au lieu de parallèle.
la source
La planification classique des tâches peut être série , parallèle ou simultanée .
Série : les tâches doivent être exécutées l'une après l'autre dans un ordre trompé connu ou cela ne fonctionnera pas. Assez facile.
Parallèle : les tâches doivent être exécutées en même temps ou cela ne fonctionnera pas.
Essayez d'éviter cela ou nous aurons des larmes à l'heure du thé.
Concurrent : on s'en fout. Mais nous ne sommes pas négligents: nous l'avons analysé et cela n'a pas d'importance; nous pouvons donc exécuter n'importe quelle tâche en utilisant n'importe quelle installation disponible à tout moment. Jours heureux.
Souvent, la programmation disponible change lors d'événements connus que nous appelons un changement d'état.
Les gens pensent souvent qu'il s'agit de logiciels, mais c'est en fait un concept de conception de systèmes qui précède les ordinateurs; les systèmes logiciels ont été un peu lents dans leur adoption, très peu de langages logiciels tentent même de résoudre le problème. Vous pouvez essayer de rechercher l' occam de la langue du transputer si vous êtes intéressé.
En résumé, la conception des systèmes aborde les points suivants:
Bonne chance.
la source
J'ai compris que la différence était:
1) Concurrent - exécuté en tandem en utilisant des ressources partagées 2) Parallèle - exécuté côte à côte en utilisant différentes ressources
Ainsi, vous pouvez avoir deux choses qui se produisent en même temps indépendamment l'une de l'autre, même si elles se rejoignent aux points (2) ou deux choses tirant sur les mêmes réserves tout au long des opérations en cours d'exécution (1).
la source
Bien qu'il n'y ait pas d'accord complet sur la distinction entre les termes parallèle et concurrent , de nombreux auteurs font les distinctions suivantes:
Les programmes parallèles sont donc simultanés, mais un programme tel qu'un système d'exploitation multitâche est également simultané, même lorsqu'il est exécuté sur une machine avec un seul cœur, car plusieurs tâches peuvent être en cours à tout moment.
Source : Introduction à la programmation parallèle, Peter Pacheco
la source
Source de simultanéité et de parallélisme
Dans un processus multithread sur un seul processeur, le processeur peut basculer les ressources d'exécution entre les threads, résultant en une exécution simultanée .
Dans le même processus multithread dans un environnement multiprocesseur à mémoire partagée, chaque thread du processus peut s'exécuter sur un processeur distinct en même temps, ce qui entraîne une exécution parallèle .
Lorsque le processus a moins ou autant de threads qu'il y a de processeurs, le système de prise en charge des threads conjointement avec l'environnement d'exploitation garantit que chaque thread s'exécute sur un processeur différent.
Par exemple, dans une multiplication matricielle ayant le même nombre de threads et de processeurs, chaque thread (et chaque processeur) calcule une ligne du résultat.
la source
Différentes personnes parlent de différents types de simultanéité et de parallélisme dans de nombreux cas spécifiques différents, de sorte que certaines abstractions pour couvrir leur nature commune sont nécessaires.
L'abstraction de base se fait en informatique, où simultanéité et parallélisme sont attribués aux propriétés des programmes . Ici, les programmes sont des descriptions formalisées de l'informatique. Ces programmes n'ont pas besoin d'être dans un langage ou un codage particulier, qui est spécifique à l'implémentation. L'existence d'API / ABI / ISA / OS n'est pas pertinente pour un tel niveau d'abstraction. Certes, il faudra des connaissances spécifiques à l'implémentation plus détaillées (comme le modèle de threading) pour effectuer des travaux de programmation concrets, l'esprit derrière l'abstraction de base n'est pas changé.
Un deuxième fait important est que, comme propriétés générales, la concurrence et le parallélisme peuvent coexister dans de nombreuses abstractions différentes .
Pour la distinction générale, voir la réponse pertinente pour la vue de base de la concurrence par rapport au parallélisme. (Il existe également des liens contenant des sources supplémentaires.)
La programmation simultanée et la programmation parallèle sont des techniques pour implémenter de telles propriétés générales avec certains systèmes qui exposent la programmabilité. Les systèmes sont généralement des langages de programmation et leurs implémentations.
Un langage de programmation peut exposer les propriétés souhaitées par des règles sémantiques intégrées. Dans la plupart des cas, ces règles spécifient les évaluations de structures de langage spécifiques (par exemple les expressions) rendant le calcul impliqué effectivement simultané ou parallèle. (Plus précisément, les effets de calcul impliqués par les évaluations peuvent parfaitement refléter ces propriétés.) Cependant, la sémantique du langage simultané / parallèle est essentiellement complexe et n'est pas nécessaire aux travaux pratiques (pour implémenter des algorithmes efficaces simultanés / parallèles comme solutions de problèmes réalistes). ). Ainsi, la plupart des langues traditionnelles adoptent une approche plus conservatrice et plus simple: en supposant la sémantique de l' évaluation totalement séquentielle et en série, puis en fournissant des primitives en option pour permettre unedes calculs étant simultanés et parallèles. Ces primitives peuvent être des mots-clés ou des constructions procédurales ("fonctions") supportées par le langage. Ils sont implémentés sur la base de l'interaction avec des environnements hébergés (OS, ou interface matérielle "bare metal"), généralement opaques (ne pouvant pas être dérivées en utilisant la langue de manière portable) à la langue. Ainsi, dans ce type particulier d'abstractions de haut niveau vues par les programmeurs, rien n'est concurrent / parallèle à part ces primitives "magiques" et les programmes s'appuyant sur ces primitives; les programmeurs peuvent alors profiter d'une expérience de programmation moins sujette aux erreurs lorsque les propriétés de concurrence / parallélisme ne sont pas si intéressées.
Bien que les primitives enlèvent le complexe dans les abstractions de plus haut niveau, les implémentations ont toujours la complexité supplémentaire non exposée par la fonction de langage. Ainsi, certaines abstractions de niveau intermédiaire sont nécessaires. Un exemple typique est le filetage . Le thread permet un ou plusieurs threads d'exécution (ou simplement thread ; parfois il est aussi appelé un processus , ce qui n'est pas nécessairement le concept d'une tâche planifiée dans un OS) supporté par l'implémentation du langage (le runtime). Les threads sont généralement planifiés de manière préventive par le runtime, donc un thread n'a besoin de rien savoir sur les autres threads. Ainsi, les threads sont naturels pour implémenter le parallélisme tant qu'ils ne partagent rien (les ressources critiques): il suffit de décomposer les calculs dans différents threads, une fois que l'implémentation sous-jacente permet le chevauchement des ressources de calcul lors de l'exécution, ça marche. Les threads sont également soumis à des accès simultanés de ressources partagées: le simple accès aux ressources dans n'importe quel ordre répond aux contraintes minimales requises par l'algorithme, et l'implémentation déterminera éventuellement le moment de l'accès. Dans de tels cas, certaines opérations de synchronisation peuvent être nécessaires. Certains langages traitent les opérations de threading et de synchronisation comme faisant partie de l'abstraction de haut niveau et les exposent comme des primitives, tandis que d'autres langages n'encouragent que des primitives de relativement plus haut niveau (comme les futurs / promesses ).
Sous le niveau des threads spécifiques à la langue, il y a le multitâche de l'environnement d'hébergement sous-jacent (généralement, un système d'exploitation). Le multitâche préemptif au niveau du système d'exploitation est utilisé pour implémenter le multithreading (préemptif). Dans certains environnements comme Windows NT, les unités de planification de base (les tâches) sont également des «threads». Pour les différencier avec l'implémentation en espace utilisateur des threads mentionnés ci-dessus, ils sont appelés threads du noyau, où "noyau" signifie le noyau du système d'exploitation (cependant, à proprement parler, ce n'est pas tout à fait vrai pour Windows NT; le "vrai" noyau est le NT exécutif) . Les threads du noyau ne sont pas toujours mappés 1: 1 aux threads de l'espace utilisateur, bien que le mappage 1: 1 réduise souvent la plupart des frais généraux de mappage. Étant donné que les threads du noyau sont lourds (impliquant des appels système) pour créer / détruire / communiquer,fils verts dans l'espace utilisateur pour surmonter les problèmes de surcharge au détriment de la surcharge de mappage. Le choix de la cartographie en fonction du paradigme de programmation attendu dans l'abstraction de haut niveau. Par exemple, lorsqu'un grand nombre de threads de l'espace utilisateur devraient être exécutés simultanément (comme Erlang ), le mappage 1: 1 n'est jamais réalisable.
Le multitâche OS est sous-jacent au multitâche de niveau ISA fourni par le cœur logique du processeur. Il s'agit généralement de l'interface publique de bas niveau pour les programmeurs. En dessous de ce niveau, il peut exister SMT . Il s'agit d'une forme de multithreading de plus bas niveau implémentée par le matériel, mais sans doute encore quelque peu programmable - bien qu'elle ne soit généralement accessible que par le fabricant du processeur. Notez que la conception matérielle reflète apparemment le parallélisme, mais il existe également un mécanisme de planification simultanée pour utiliser efficacement les ressources matérielles internes.
Dans chaque niveau de "threading" mentionné ci-dessus, la simultanéité et le parallélisme sont impliqués. Bien que les interfaces de programmation varient considérablement, toutes sont soumises aux propriétés révélées par l'abstraction de base au tout début.
la source
Je partage juste un exemple qui aide à mettre en évidence la distinction:
Programmation parallèle: Supposons que vous souhaitiez implémenter l' algorithme de fusion-tri . Chaque fois que vous divisez le problème en deux sous-problèmes, vous pouvez avoir deux threads qui les résolvent. Cependant, pour effectuer l'étape de fusion, vous devez attendre la fin de ces deux threads, car la fusion nécessite les deux sous-solutions. Cette «attente obligatoire» en fait un programme parallèle.
Programme simultané: Supposons que vous souhaitez compresser n fichiers texte et générer un fichier compressé pour chacun d'eux. Vous pouvez avoir de 2 (jusqu'à n) threads qui traitent chacun la compression d'un sous-ensemble des fichiers. Lorsque chaque thread est terminé, c'est juste terminé, il n'a pas à attendre ou à faire autre chose. Ainsi, puisque différentes tâches sont exécutées de manière entrelacée dans "n'importe quel ordre arbitraire", le programme est simultané mais pas parallèle.
Comme quelqu'un d'autre l'a mentionné, chaque programme parallèle est simultané (doit être en fait), mais pas l'inverse.
la source
Je vais essayer de l'expliquer dans mon propre style, ce n'est peut-être pas en termes informatiques mais ça vous donne une idée générale.
Prenons un exemple, disons les tâches ménagères: nettoyer la vaisselle, sortir les ordures, tondre la pelouse, etc., nous avons également 3 personnes (fils) A, B, C pour les faire
Simultanément: les trois individus commencent différentes tâches indépendamment, c.-à-d.
Ici, l'ordre des tâches est indéterministe et les réponses dépendent de la quantité de travail
Parallèle: ici, si nous voulons améliorer le débit, nous pouvons affecter plusieurs personnes à la même tâche, par exemple, nettoyer la vaisselle, nous affectons deux personnes, A savonner la vaisselle et B laver la vaisselle, ce qui pourrait améliorer le débit.
nettoyage de la vaisselle:
bientôt
J'espère que cela donne une idée! passons maintenant aux termes techniques qui sont expliqués dans les autres réponses;)
la source