web-dev-qa-db-ja.com

並行プログラミングと並列プログラミングの違いは何ですか?

並行プログラミングと並列プログラミングの違いは何ですか?私はグーグルに尋ねましたが、その違いを理解するのに役立つものは見つかりませんでした。両方の例を挙げていただけますか?

今のところ、私はこの説明を見つけました: http://www.linux-mag.com/id/7411 -しかし、「並行性はプログラムの特性です」対「並列実行はマシンの特性です「私には十分ではありません-それでも何が何であるかを言うことはできません。

318
matekm

プログラムがスレッドを使用している場合(同時プログラミング)、マシンが複数のスレッドを処理できるかどうかに依存するため、必ずしもそのように実行されるわけではありません(並列実行)。

これが視覚的な例です。 非スレッドマシン上のスレッド:

        --  --  --
     /              \
>---- --  --  --  -- ---->>

threadedマシン上のスレッド:

     ------
    /      \
>-------------->>

ダッシュは実行されたコードを表します。ご覧のとおり、これらは両方とも別々に分割されて実行されますが、スレッドマシンは複数の個別の部分を一度に実行できます。

288
Tor Valamo

並行プログラミングは、重複しているように見える操作を考慮し、主に非決定論的な制御フローのために生じる複雑さに関係しています。並行プログラムに関連する定量的コストは、通常、スループットと待ち時間の両方です。並行プログラムは、多くの場合IOバインドされますが、常にではありません。コンカレントガベージコレクターは完全にCPU上にあります。並行プログラムの教育的な例は、Webクローラーです。このプログラムは、Webページの要求を開始し、ダウンロードの結果が利用可能になったときに応答を同時に受け入れ、既にアクセスしたページのセットを蓄積します。プログラムが実行されるたびに応答が必ずしも同じ順序で受信されるとは限らないため、制御フローは非決定的です。この特性により、並行プログラムのデバッグが非常に難しくなります。一部のアプリケーションは、基本的に並行しています。 Webサーバーはクライアント接続を同時に処理する必要があります。 Erlangはおそらく、高度な並行プログラミングのための最も有望な言語です。

並列プログラミングは、スループットを改善するという特定の目標のために重複する操作に関係します。並行プログラミングの難しさは、制御フローを決定論的にすることで回避されます。通常、プログラムは並行して実行される子タスクのセットを生成し、親タスクはすべてのサブタスクが終了した後にのみ継続します。これにより、並列プログラムのデバッグがはるかに簡単になります。並列プログラミングの難しい部分は、粒度や通信などの問題に関するパフォーマンスの最適化です。後者は、1つのキャッシュから別のキャッシュへのデータ転送に関連するかなりのコストがあるため、マルチコアのコンテキストでは依然として問題です。密行列-行列乗算は、並列プログラミングの教育的例であり、Straasenの分割統治アルゴリズムを使用し、副問題を並列に攻撃することで効率的に解決できます。 Cilkは、おそらく共有メモリコンピューター(マルチコアを含む)での高性能並列プログラミングに最も有望な言語です。

377
Jon Harrop

https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html

同時= 2つのキューと1つのコーヒーマシン。

並列= 2つのキューと2つのコーヒーマシン。

130
GKislin

元の質問をprogrammingではなくparallel/concurrentcomputationとして解釈します。

同時計算では、2つの計算が両方とも互いに独立して進みます。 2番目の計算は、最初の計算が完了するまで待つ必要はありません。しかし、それがどのように達成されるかというメカニズムについては述べていません。シングルコアセットアップでは、スレッド間の中断と切り替えが必要です(preemptiveマルチスレッドとも呼ばれます)。

並列計算では、2つの計算が両方とも同時に進行します-文字通り同時に実行されます。これはシングルCPUでは不可能であり、代わりにマルチコアセットアップが必要です。

suspending and taking turns 対 parallel computing

「Node.jsでの並列と並行」

32
pspi

プロセッサからのビューでは、この写真で説明できます

In the view from a processor, It can be described by this pic

プロセッサからのビューでは、この写真で説明できます

21
mohsen.nour

並行プログラミングとは、ハードウェアの詳細から省略した複数のスレッドをプログラムで実行できるようにするマルチスレッドプログラミングのことです。

並列プログラミングとは、利用可能な並列実行を活用するためにプログラムアルゴリズムを特別に設計することです。たとえば、最初に最初のブランチをチェックしてから2番目のブランチをチェックした場合よりも(平均して)早く結果にヒットすることを期待して、いくつかのアルゴリズムの2つのブランチを並行して実行できます。

19
user151323

このコンテンツはいくつかのブログで見つけました。それは有用で関連があると思った。

並行性と並列性は同じものではありません。 2つのタスクが時間内に実行される順序が事前に決定されていない場合、2つのタスクT1とT2は同時に実行されます。

T1がT2の前に実行されて終了し、T2がT1の前に実行されて終了し、T1とT2が同じ時間に同時に実行され(並列性)、T1とT2が交互に実行される場合があります。 1つのシングルコア非SMT非CMPプロセッサで実行するようにOSによってスケジュールされている場合、並行性は得られますが、並列性は得られません。並列処理は、マルチコア、マルチプロセッサ、または分散システムで可能です。

並行性は、多くの場合、プログラムのプロパティと呼ばれ、並列処理よりも一般的な概念です。

ソース: https://blogs.Oracle.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming

13
loknath

それらは、(わずかに)異なる視点から同じことを説明する2つのフレーズです。並列プログラミングとは、ハードウェアの観点から状況を説明するものです。少なくとも2つのプロセッサが(おそらく単一の物理パッケージ内に)並列に問題に取り組んでいます。並行プログラミングは、ソフトウェアの観点からより多くのことを記述しています。2つ以上のアクションがまったく同時に(並行して)発生する可能性があります。

ここでの問題は、人々が2つのフレーズを使用して、実際に存在しない場合に明確な区別をしようとしていることです。現実には、彼らが描画しようとしている境界線は何十年もあいまいで不明瞭であり、時間とともにさらに不明瞭になっています。

彼らが議論しようとしているのは、かつて、ほとんどのコンピューターに単一のCPUしかなかったという事実です。その単一のCPUで複数のプロセス(またはスレッド)を実行した場合、CPUは実際には一度にそれらのスレッドの1つから1つの命令のみを実行していました。並行性の出現は幻想でした.CPUは、さまざまなスレッドからの命令の実行を、人間の知覚(100ミリ秒未満が瞬時に見える)に十分な速さで切り替えることで、一度に多くのことを行っているように見えました。

これとは明らかに対照的なのが、複数のCPUを搭載したコンピューター、または複数のコアを搭載したCPUです。したがって、マシンは複数のスレッドやプロセスからの命令をまったく同時に実行しています。一方を実行するコードは、他方で実行するコードに影響を与えることはできません。

さて、問題:このような明確な区別にはalmostは存在しませんでした。コンピューター設計者は実際かなり頭がいいので、(たとえば)ディスクなどのI/Oデバイスからデータを読み取る必要があるとき、long時間( CPUサイクルの観点から)終了します。その間、CPUをアイドル状態のままにする代わりに、1つのプロセス/スレッドにI/O要求を行わせ、I/O要求の完了中に他のプロセス/スレッドからのコードをCPUで実行させるさまざまな方法を見つけました。

そのため、マルチコアCPUが標準になるずっと前から、複数のスレッドからの操作が並行して行われていました。

しかし、それは氷山の一角にすぎません。数十年前、コンピューターは別のレベルの並列処理も提供し始めました。繰り返しになりますが、コンピューターの設計者はかなり頭がいいので、多くの場合、互いに影響を与えない命令を持っていることに気付きました。したがって、同じストリームから複数の命令を同時に実行することができました。よく知られるようになった初期の例の1つはControl Data 6600でした。これは1964年に導入されたとき、地球上で(かなり広いマージンで)最も高速なコンピューターでした。各命令で使用されるリソースを追跡し、それらが依存するリソースが利用可能になるとすぐに命令を実行する一連の実行ユニットがあり、最新のIntel/AMDプロセッサの設計と非常に似ていました。

しかし、(コマーシャルが言っていたように)待ってください。さらに混乱を加えるための設計要素がもう1つあります。非常に多くの異なる名前が付けられています(例:「ハイパースレッディング」、「SMT」、「CMP」)が、それらはすべて同じ基本概念を指します:CPUは、いくつかのリソースの組み合わせを使用して、同時に複数のスレッドを実行できますスレッドごとに独立しており、スレッド間で共有される一部のリソース。典型的な場合、これは上記の命令レベルの並列処理と組み合わされます。そのために、2つ(またはそれ以上)のアーキテクチャレジスタがあります。次に、必要なリソースが利用可能になるとすぐに命令を実行できる実行ユニットのセットがあります。別々のストリームからの命令が事実上同じリソースに依存することはないため、これらはしばしばうまく組み合わされます。

それから、もちろん、複数のコアを持つ最新のシステムに到達します。ここでは明らかですよね? N個(現時点では2から256程度)の別個のコアがあり、すべて同時に命令を実行できるため、実際の並列処理の明確なケースがあります-1つのプロセス/スレッドで命令を実行すると、 tは、別の命令の実行に影響します。

まあ、ちょっと。ここでも、いくつかの独立したリソース(レジスタ、実行ユニット、少なくとも1レベルのキャッシュ)といくつかの共有リソース(通常、少なくとも最低レベルのキャッシュ、メモリコントローラーとメモリへの帯域幅)があります。

要約すると、人々が共有リソースと独立したリソースを対比させたいという単純なシナリオは、実際には決して起こりません。すべてのリソースが共有されると、MS-DOSのようなものになり、一度に1つのプログラムしか実行できず、もう1つを実行する前に1つのプログラムの実行を停止する必要があります。完全に独立したリソースを使用して、MS-DOSを実行するN台のコンピューターがあり(それらを接続するネットワークさえもなし)、それらの間で何も共有することはできません(ファイルを共有することさえできれば、それは共有リソースです。何も共有されないという基本的な前提の違反)。

すべての興味深いケースには、独立したリソースと共有リソースの組み合わせが含まれます。合理的にすべての現代のコンピューター(およびまったく現代的ではない多くのコンピューター)には、少なくともいくつかの独立した操作を同時に実行する能力が少なくともあり、MS-DOSがそれを利用して洗練されたものは少なくともある程度。

人々が描くのを好む「並行」と「並行」のすてきな、きれいな区分は存在せず、ほとんどありません。人々が「同時」として分類したいものには、通常、少なくとも1つ以上の異なるタイプの並列実行が含まれます。彼らが「並列」として分類したいのは、多くの場合、リソースを共有し、(たとえば)1つのプロセスが別の実行をブロックし、2つの間で共有されるリソースを使用することです。

「並行」と「並行」を明確に区別しようとする人々は、実際には存在しなかったコンピューターのファンタジーに住んでいます。

7
Jerry Coffin

タスクのクラシックスケジューリングは、serialparallelまたはconcurrent

  • Serial:タスクは既知のだまされた順序で次々に実行する必要があります。そうしないと機能しません。簡単です。

  • Parallel:タスクは同時に実行する必要があります。そうしないと機能しません。

    • 機能的にまたは時間内に、タスクのいずれかの障害が発生すると、システム全体の障害が発生します。
    • すべてのタスクには、共通の信頼できる時間感覚が必要です。

    これを避けるようにしてください。そうしないと、ティータイムまでに涙が出ます。

  • Concurrent:気にしません。しかし、私たちは不注意ではありません。それを分析しましたが、問題ではありません。したがって、いつでも利用可能な機能を使用してタスクを実行できます。幸せな日々。

多くの場合、使用可能なスケジューリングは、状態の変更と呼ばれる既知のイベントで変更されます。

多くの場合、これはソフトウェアに関するものだと考えられますが、実際にはコンピューターよりも前のシステム設計の概念です。ソフトウェアシステムの取り込みは少し遅く、問題に対処しようとするソフトウェア言語はほとんどありません。興味がある場合は、トランスピュータ言語occamを検索してみてください。

簡潔に言うと、システム設計は次のことに対処します。

  • 動詞-あなたがしていること(操作またはアルゴリズム)
  • 名詞-何をするか(データまたはインターフェース)
  • いつ-開始、スケジュール、状態変更
  • 方法-シリアル、パラレル、同時
  • どこ-物事がいつ起こるかがわかれば、それが起こる前にではなく、どこで起こるかを言うことができます。
  • なぜ-これがそれを行う方法ですか?他の方法があり、さらに重要なのは、better方法ですか?しないとどうなりますか?

がんばろう。

5
Don

プログラミングでは、並行性は独立して実行されるプロセスの構成であり、並列性は(関連する可能性のある)計算の同時実行です。
-Andrew Gerrand-

そして

同時実行性は、独立して実行される計算の構成です。並行性は、特に現実の世界とうまくやり取りするクリーンなコードを記述する方法として、ソフトウェアを構築する方法です。それは並列処理ではありません。

並行処理は並列処理を可能にしますが、並行処理ではありません。プロセッサが1つしかない場合でも、プログラムは同時に実行できますが、並列にはできません。一方、適切に作成された並行プログラムは、マルチプロセッサー上で効率的に並列実行できます。そのプロパティは重要かもしれません...
-Rob Pike-

違いを理解するために、このRob Pike(Golangクリエイターの1人)のビデオを見ることを強くお勧めします。 同時実行性は並列処理ではありません

5
Jinbom Heo

並列プログラミングは、コードが同時に実行され、各実行が互いに独立している場合に発生します。そのため、通常は共有変数などに専念することはありません。なぜなら、それは起こりそうにないからです。

ただし、並行プログラミングは、変数などを共有するさまざまなプロセス/スレッドによって実行されるコードで構成されているため、並行プログラミングでは、どのプロセス/スレッドを最初に実行するかを決定する何らかのルールを確立する必要があります。一貫性があり、何が起こるかを確実に知ることができます。制御がなく、すべてのスレッドが同時に計算し、同じ変数に物事を保存する場合、最終的に何を期待するのかをどのように知ることができますか?スレッドは他のスレッドよりも高速かもしれません。スレッドの1つが実行中に停止し、別のスレッドが破損した(まだ完全には計算されていない)変数で別の計算を続行した可能性があります。このような状況で、通常は並列ではなく並行プログラミングを使用します。

5
sharp_c-tudent
  • Concurrent programmingは、一般的な意味で、定義したタスクが任意の順序で発生する可能性がある環境を指します。 1つのタスクは別のタスクの前または後に実行でき、一部またはすべてのタスクを同時に実行できます。

  • Parallel programmingは、異なるプロセッサでの同時タスクの同時実行を具体的に指すことです。したがって、すべての並列プログラミングは並行ですが、すべての並行プログラミングが並列であるとは限りません。

ソース: PThreadsプログラミング-より良いマルチプロセッシングのためのPOSIX標準、Butlar、Farrell、Nichols

5
snr

私はその違いを理解しました:

1)同時-共有リソースを使用して並行して実行2)並列-異なるリソースを使用して並行して実行

そのため、ポイント(2)で一緒になった場合でも、実行中の操作全体で同じリザーブを使用している場合でも(1)、2つのことが同時に独立して発生します。

3
Jonathan

用語parallelconcurrentの区別について完全な合意はありませんが、多くの著者は次の区別をしています:

  • コンカレントコンピューティングでは、プログラムとは、複数のタスクをいつでも進行させることができるプログラムです。
  • 並列計算では、プログラムは複数のタスクが密接に協力して問題を解決するものです。

したがって、並列プログラムは同時実行されますが、マルチタスクオペレーティングシステムなどのプログラムは、コアが1つだけのマシンで実行されている場合でも、同時に実行されます。

ソース:並列プログラミング入門、Peter Pacheco

1
zbs

並行性と並列性ソース

シングルプロセッサ上のマルチスレッドプロセスでは、プロセッサはスレッド間で実行リソースを切り替えることができるため、同時実行が発生します

共有メモリマルチプロセッサ環境の同じマルチスレッドプロセスでは、プロセス内の各スレッドを別々のプロセッサで同時に実行できるため、結果としてparallel execution

プロセスに含まれるスレッドの数がプロセッサーの数よりも少ない場合、またはスレッドがシステムをサポートしている場合、オペレーティングシステムは各スレッドが異なるプロセッサーで実行されるようにします。

たとえば、スレッドとプロセッサの数が同じ行列乗算では、各スレッド(および各プロセッサ)は結果の行を計算します。

0
nanosoft

さまざまな人々がさまざまな特定のケースでさまざまな種類の並行性と並列性について話しているため、それらの共通の性質をカバーするいくつかの抽象化が必要です。

基本的な抽象化はコンピューターサイエンスで行われます。ここでは、同時実行性と並列処理の両方がprogramsのプロパティに起因します。ここで、プログラムはコンピューティングの形式化された説明です。そのようなプログラムは、特定の言語またはエンコーディングである必要はありません。これは実装固有です。 API/ABI/ISA/OSの存在は、このような抽象化レベルとは無関係です。確かに、具体的なプログラミング作業を行うには、より詳細な実装固有の知識(スレッドモデルなど)が必要になりますが、基本的な抽象化の背後にある精神は変わりません。

2番目の重要な事実は、一般的なプロパティとして、並行処理と並列処理は多くの異なる抽象化で共存できるです。

一般的な区別については、並行性と並列性の基本的なビューについては 関連する回答 を参照してください(いくつかの追加ソースを含むリンクもあります。)

並行プログラミングと並列プログラミングは、プログラマビリティを公開するいくつかのシステムでこのような一般的なプロパティを実装する手法です。システムは通常、プログラミング言語とその実装です。

プログラミング言語は、組み込みのセマンティックルールによって目的のプロパティを公開する場合があります。ほとんどの場合、このようなルールは、特定の言語構造(式など)の評価を指定して、計算を効果的に並行または並列に関与させます。 (より具体的には、評価によって暗示される計算効果はこれらの特性を完全に反映することができます。)ただし、同時/並列言語のセマンティクスは本質的に複雑であり、実用的な作業には必要ありません(現実的な問題の解決策として効率的な同時/並列アルゴリズムを実装するため) )。そのため、ほとんどの従来の言語は、より保守的でシンプルなアプローチを採用しています。評価のセマンティクスを完全にシーケンシャルでシリアルに想定し、オプションのプリミティブを提供して、同時および並列の計算のsomeを可能にします。これらのプリミティブは、言語でサポートされるキーワードまたは手続き構造(「関数」)です。それらは、ホスト環境(OS、または「ベアメタル」ハードウェアインターフェイス)との相互作用に基づいて実装され、通常は言語に対して不透明(言語を使用して派生することはできません)です。したがって、プログラマーに見られるこの特定の種類の高レベルの抽象化では、これらの「魔法の」プリミティブとこれらのプリミティブに依存するプログラム以外に並行/並列はありません。並行性/並列性のプロパティにあまり関心がない場合、プログラマはエラーの少ないプログラミングの経験を楽しむことができます。

プリミティブは、最も高レベルの抽象化では複雑さを抽象化しますが、実装には、言語機能で公開されていない余分な複雑さがあります。そのため、いくつかの中レベルの抽象化が必要です。 1つの典型的な例は、threadingです。スレッド化により、1つ以上のthread of execution(または単にthread;時にはprocessと呼ばれることもあります) 、これは必ずしもOSでスケジュールされたタスクの概念ではありません)、言語実装(ランタイム)でサポートされています。通常、スレッドはランタイムによってプリエンプティブにスケジュールされるため、スレッドは他のスレッドについて何も知る必要がありません。したがって、スレッドは何も共有しない限り(重要なリソース)並列を実装するのが自然です:基になる実装が計算リソースの重複を許可すると、異なるスレッドで計算を分解するだけです実行、それは動作します。スレッドは共有リソースの同時アクセスの対象にもなります。任意の順序でリソースにアクセスするだけで、アルゴリズムに必要な最小限の制約が満たされ、実装は最終的にアクセスするタイミングを決定します。このような場合、同期操作が必要になる場合があります。一部の言語は、スレッド化および同期操作を高レベルの抽象化の一部として扱い、それらをプリミティブとして公開しますが、他の一部の言語は、比較的高レベルのプリミティブのみを推奨します( futures/promises など)。

言語固有のスレッドのレベルでは、基礎となるホスティング環境(通常はOS)のマルチタスクが発生します。 OSレベルのプリエンプティブマルチタスクは、(プリエンプティブ)マルチスレッドを実装するために使用されます。 Windows NTなどの一部の環境では、基本的なスケジューリング単位(タスク)も「スレッド」です。上記のスレッドのユーザー空間実装でそれらを区別するために、それらはカーネルスレッドと呼ばれます。「カーネル」はOSのカーネルを意味します (ただし、厳密に言えば、これはWindows NTには当てはまりません。「実際の」カーネルはNTエグゼクティブです)。カーネルスレッドは、ユーザー空間のスレッドに常に1:1でマッピングされるとは限りませんが、1:1マッピングはマッピングのオーバーヘッドをほとんど削減します。カーネルスレッドは(システムコールを含む)作成/破棄/通信するためのヘビーウェイトであるため、マッピングオーバーヘッドを犠牲にしてオーバーヘッドの問題を克服するために、ユーザー空間に非1:1 グリーンスレッド があります。高レベルの抽象化で予想されるプログラミングパラダイムに応じたマッピングの選択。たとえば、膨大な数のユーザースペーススレッドが同時に実行されると予想される場合( Erlang など)、1:1マッピングは不可能です。

OSマルチタスクの基礎は、プロセッサの論理コアによって提供されるISAレベルのマルチタスクです。これは通常、プログラマ向けの最も低レベルのパブリックインターフェイスです。このレベルの下には、 SMT が存在する場合があります。これは、ハードウェアによって実装される、より低レベルのマルチスレッドの形式ですが、おそらくある程度プログラミング可能ですが、通常はプロセッサの製造元のみがアクセスできます。ハードウェア設計は明らかに並列性を反映していることに注意してください。ただし、内部ハードウェアリソースを効率的に使用するための同時スケジューリングメカニズムもあります。

上記の「スレッド化」の各レベルでは、並行性と並列性の両方が関係しています。プログラミングインターフェイスは劇的に異なりますが、それらはすべて、最初の基本的な抽象化によって明らかにされたプロパティに従います。

0
FrankHB