並行プログラミングと並列プログラミングの違いは何ですか?私はグーグルに尋ねましたが、その違いを理解するのに役立つものは何も見つかりませんでした。両方の例を教えていただけますか?
今のところ私はこの説明を見つけました:http : //www.linux-mag.com/id/7411-「並行性はプログラムのプロパティです」vs「並列実行はマシンのプロパティ」では十分ではありません-それでも私は何が何であるか言うことができません。
並行プログラミングと並列プログラミングの違いは何ですか?私はグーグルに尋ねましたが、その違いを理解するのに役立つものは何も見つかりませんでした。両方の例を教えていただけますか?
今のところ私はこの説明を見つけました:http : //www.linux-mag.com/id/7411-「並行性はプログラムのプロパティです」vs「並列実行はマシンのプロパティ」では十分ではありません-それでも私は何が何であるか言うことができません。
回答:
プログラムがスレッドを使用している場合(並行プログラミング)、マシンが複数のスレッドを処理できるかどうかに依存するため、スレッドが実行される(並列実行)とは限りません。
これは視覚的な例です。非スレッドマシン上のスレッド:
-- -- --
/ \
>---- -- -- -- -- ---->>
スレッドマシン上のスレッド:
------
/ \
>-------------->>
ダッシュは実行されたコードを表します。ご覧のように、それらは分割されて別々に実行されますが、スレッドマシンは複数の個別の部分を一度に実行できます。
並行プログラミング重複しているように見える操作について、主に非決定論的な制御フローが原因で発生する複雑さに関係しています。並行プログラムに関連する定量的なコストは、通常、スループットと待ち時間の両方です。並行プログラムは多くの場合IOにバインドされますが、常にではありません。たとえば、並行ガベージコレクターは完全にCPU上にあります。並行プログラムの教育学的な例は、Webクローラーです。このプログラムは、Webページの要求を開始し、ダウンロードの結果が利用可能になると同時に応答を受け入れ、すでにアクセスされた一連のページを蓄積します。プログラムが実行されるたびに応答が同じ順序で受信されるとは限らないため、制御フローは非決定的です。この特性により、並行プログラムのデバッグが非常に困難になる場合があります。Erlang、F#非同期ワークフロー、およびScalaのAkkaライブラリは、高度な並行プログラミングに対するおそらく最も有望なアプローチです。
マルチコアプログラミング並列プログラミングの特殊なケースです。並列プログラミングは、スループットを向上させるという特定の目標のために重複する操作に関係しています。並行プログラミングの難しさは、制御フローを確定的にすることによって回避されます。通常、プログラムは並列に実行される子タスクのセットを生成し、親タスクはすべてのサブタスクが終了した後にのみ続行されます。これにより、並列プログラムよりも並列プログラムのデバッグがはるかに容易になります。並列プログラミングの難しい部分は、粒度や通信などの問題に関するパフォーマンスの最適化です。後者は、マルチコアのコンテキストでは依然として問題です。1つのキャッシュから別のキャッシュへのデータ転送にかなりのコストがかかるためです。Cilkは、おそらくマルチコア上での高性能並列プログラミングの最も有望なアプローチであり、IntelのスレッドビルディングブロックとMicrosoftのTask Parallel Library(.NET 4内)の両方で採用されています。
https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html
同時= 2つのキューと1つのコーヒーマシン。
Parallel = 2つのキューと2つのコーヒーマシン。
元の質問をプログラミングではなく並列/並行計算として解釈する。
で2つの計算両方予め同時計算互いに独立。2番目の計算は、最初の計算が完了するまで待つ必要はありません。しかし、それがどのようにして達成されるかのメカニズムは述べられていません。シングルコアセットアップでは、一時停止とスレッド間の切り替えが必要です(プリエンプティブマルチスレッドとも呼ばれます)。
で並列計算、同時に2つの計算の両方を予め同時に文字通り-です。これはシングルCPUでは不可能であり、代わりにマルチコアセットアップが必要です。
記事の画像:「Node.jsでの並行性と並行性」
対
並行プログラミングとは、ハードウェアの詳細から抽象化された、プログラムに複数のスレッドを実行させるマルチスレッドプログラミングを指していると思います。
並列プログラミングとは、利用可能な並列実行を利用するようにプログラムアルゴリズムを特別に設計することです。たとえば、いくつかのアルゴリズムの2つのブランチを並列に実行して、最初にチェックしてから2番目のブランチをチェックした場合よりも(平均して)結果に早く到達することを期待できます。
このコンテンツをいくつかのブログで見つけました。それは便利で関連性があると思いました。
並行性と並列性は同じものではありません。2つのタスクT1とT2は、2つのタスクが時間内に実行される順序が事前に決定されていない場合、同時に実行されます。
T1はT2の前に実行および終了され、T2はT1の前に実行および終了され、T1およびT2は同時に実行されます(並列処理)。T1とT2は交互に実行されます。 OSによって1つのシングルコア非SMT非CMPプロセッサで実行するようにスケジュールされている場合、同時実行性は得られますが、並列性は得られません。並列処理は、マルチコア、マルチプロセッサ、または分散システムで可能です。
並行性はプログラムのプロパティと呼ばれることが多く、並列処理よりも一般的な概念です。
ソース:https : //blogs.oracle.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming
それらは、(非常にわずかに)異なる視点から同じことを説明する2つのフレーズです。並列プログラミングは、ハードウェアの観点から状況を説明しています。少なくとも2つのプロセッサ(単一の物理パッケージ内にある可能性があります)が並列で問題に取り組んでいます。並行プログラミングは、ソフトウェアの観点からより多くのことを記述しています。2つ以上のアクションが同時に(並行して)発生する可能性があります。
ここでの問題は、実際には何も存在しないときに、人々が2つのフレーズを使用して明確な区別を付けようとしていることです。現実には、彼らが描こうとしている境界線は何十年もあいまいで不明瞭であり、時間の経過とともにますます不明瞭になっています。
彼らが議論しようとしているのは、かつて、ほとんどのコンピュータが単一のCPUしか持っていなかったという事実です。その単一のCPUで複数のプロセス(またはスレッド)を実行したとき、CPUは実際には一度にそれらのスレッドの1つから1つの命令しか実行していませんでした。同時実行性の出現は錯覚でした-CPUがさまざまなスレッドからの命令の実行を人間の知覚(100ミリ秒未満のものは瞬時に見える)に十分速く実行することを切り替えると、一度に多くのことを実行しているように見えました。
これと明らかに対照的なのは、複数のCPUを搭載したコンピューター、または複数のコアを搭載したCPUです。そのため、マシンは複数のスレッドやプロセスからの命令をまったく同時に実行しています。一方を実行するコードは、もう一方を実行するコードに影響を与えることはできません。
ここで問題:このような明確な区別はほぼ存在しません。彼らはあなたがディスクなどのI / Oデバイスからいくつかのデータを読み取るために必要なときに(例えば)その昔は、それが取った気づいたので、コンピュータの設計者は、実際にはかなりインテリジェントある長いに(CPUサイクルの面で)時間を仕上げます。その間、CPUをアイドル状態のままにする代わりに、1つのプロセス/スレッドにI / O要求を行わせ、I / O要求の完了中に他のプロセス/スレッドからのコードをCPUで実行させるさまざまな方法を考え出しました。
したがって、マルチコアCPUが標準になるずっと前から、複数のスレッドからの操作が並行して行われていました。
それは氷山の一角にすぎません。数十年前、コンピューターは別のレベルの並列処理も提供し始めました。繰り返しになりますが、コンピュータデザイナーはかなり賢い人であり、多くの場合、互いに影響を及ぼさない命令があったため、同じストリームから複数の命令を同時に実行できることに気づきました。かなりよく知られるようになった初期の例はControl Data 6600でした。これは(かなり広いマージンで)1964年に発表されたときに地球上で最速のコンピューターであり、同じ基本アーキテクチャの多くが現在も使用されています。各命令で使用されるリソースを追跡し、依存するリソースが利用可能になるとすぐに命令を実行する一連の実行ユニットがあり、最新のIntel / AMDプロセッサの設計と非常によく似ています。
しかし、(コマーシャルが言っていたように)待ってください-それだけではありません。さらに混乱を招く設計要素がもう1つあります。かなり多くの異なる名前が付けられていますが(たとえば、「ハイパースレッディング」、「SMT」、「CMP」)、これらはすべて同じ基本的なアイデアを指します。CPUは、いくつかのリソースの組み合わせを使用して、複数のスレッドを同時に実行できますスレッドごとに独立しており、スレッド間で共有されるいくつかのリソース。典型的なケースでは、これは上記で概説した命令レベルの並列処理と組み合わされます。そのために、2つ(またはそれ以上)のアーキテクチャレジスタのセットがあります。次に、必要なリソースが利用可能になるとすぐに命令を実行できる実行ユニットのセットがあります。
次に、もちろん、複数のコアを備えた最新のシステムについて説明します。ここで物事は明白ですよね?N(現時点では2〜256程度)の別々のコアがあり、すべて同時に命令を実行できるため、実際の並列処理の明確なケースがあります。1つのプロセス/スレッドで命令を実行すると、 t別の命令の実行に影響します。
まあ、ちょっと。ここにもいくつかの独立したリソース(レジスター、実行ユニット、少なくとも1つのレベルのキャッシュ)といくつかの共有リソース(通常、少なくとも最低レベルのキャッシュ、そして間違いなくメモリコントローラーとメモリへの帯域幅)があります。
要約すると、共有リソースと独立リソースの対比を好む単純なシナリオは、実際には実際には発生しません。すべてのリソースを共有すると、MS-DOSのようになり、一度に1つのプログラムしか実行できなくなり、他のプログラムを実行する前に、1つのプログラムを停止する必要があります。完全に独立したリソースを使用して、MS-DOSを実行しているN台のコンピューター(それらを接続するためのネットワークもなし)があり、それらの間で何も共有することができません(ファイルを共有できる場合でも、それは共有リソースであり、何も共有されないという基本的な前提の違反)。
すべての興味深いケースには、独立したリソースと共有リソースの組み合わせが含まれます。合理的に現代のすべてのコンピュータ(および現代ではない多くのコンピュータ)は、少なくともいくつかの独立した操作を同時に実行する少なくともある程度の能力を持っています。ある程度。
人々が描くことを好む「並行」と「並行」の間の素敵でクリーンな区分は存在せず、ほとんど存在しません。人々が「並行」として分類したいことは、通常、少なくとも1つ、多くの場合はより多くの異なるタイプの並列実行を含みます。彼らが「並列」として分類したいのは、多くの場合、リソースの共有と(たとえば)1つのプロセスが別のプロセスの実行をブロックしている間、2つのプロセス間で共有されるリソースを使用することです。
「並行」と「並行」を明確に区別しようとする人々は、実際には存在しなかったコンピュータの幻想の中に生きています。
Concurrent programming
一般的な意味では、定義するタスクが任意の順序で発生する可能性がある環境を指します。あるタスクは別のタスクの前または後に発生する可能性があり、一部またはすべてのタスクを同時に実行できます。
Parallel programming
具体的には、異なるプロセッサ上での同時タスクの同時実行を指します。したがって、すべての並列プログラミングは並行ですが、すべての並行プログラミングが並行しているわけではありません。
ソース:PThreadsプログラミング-より良いマルチプロセッシングのためのPOSIX標準、Buttlar、Farrell、Nichols
プログラミングでは、並行性は独立して実行されるプロセスの構成であり、並列処理は(おそらく関連する)計算の同時実行です。
-アンドリュージェランド-
そして
並行性は、独立して実行される計算の構成です。並行性はソフトウェアを構築する方法であり、特に現実の世界とうまく相互作用するクリーンなコードを書く方法です。並列処理ではありません。
並行性は並列処理を可能にしますが、並列処理ではありません。プロセッサが1つしかない場合でも、プログラムは同時に実行できますが、並列にすることはできません。一方、適切に作成された並行プログラムは、マルチプロセッサー上で効率的に並列に実行できます。その性質は重要かもしれない
...-ロブ・パイク-
違いを理解するには、このRob Pike(Golangクリエイターの1人)のビデオをご覧になることを強くお勧めします。並行性は並列処理ではありません
並列プログラミングは、コードが同時に実行されており、各実行が互いに独立している場合に発生します。したがって、通常は共有変数などについては、それが発生する可能性が低いため、先入観はありません。
ただし、並行プログラミングは、変数を共有するさまざまなプロセス/スレッドによって実行されるコードなどで構成されているため、並行プログラミングでは、どのプロセス/スレッドが最初に実行されるかを決定する何らかのルールを確立する必要があります。一貫性があり、何が起こるかを確実に知ることができます。コントロールがなく、すべてのスレッドが同時に計算し、同じ変数に物事を保存する場合、最終的に何を期待するかをどのようにして知ることができるでしょうか?スレッドが他のスレッドより高速である可能性があります。スレッドの1つが実行の途中で停止し、別のスレッドが破損した(まだ完全に計算されていない)変数を使用して別の計算を続行した場合、可能性は無限です。通常、これらの状況では、並列ではなく並行プログラミングを使用します。
クラシックなタスクのスケジューリングは 、シリアル、パラレル、または同時です。
シリアル:タスクは既知のだまされた順序で次々に実行する必要があります。そうしないと機能しません。簡単です。
並列:タスクは同時に実行する必要があります。そうしないと機能しません。
これを避けてください。さもないと、ティータイムまでに涙が出ます。
同時:気にしません。しかし、私たちは不注意ではありません。私たちはそれを分析しており、それは問題ではありません。したがって、利用可能な機能を使用して、いつでもタスクを実行できます。幸せな日々。
多くの場合、使用可能なスケジューリングは、状態変化と呼ばれる既知のイベントで変化します。
多くの場合、これはソフトウェアに関するものだと考えられますが、実際には、コンピュータより以前のシステム設計コンセプトです。ソフトウェアシステムの取り込みは少し遅く、問題に対処しようとするソフトウェア言語はほとんどありません。興味があれば、トランスピューター言語occamを調べてみてください。
簡単に言うと、システム設計は次のことを扱います。
幸運を。
並行性と並列処理の ソース
シングルプロセッサ上のマルチスレッドプロセスでは、プロセッサが実行リソースをスレッド間で切り替えて、同時実行を実現できます。
共有メモリマルチプロセッサ環境の同じマルチスレッドプロセスでは、プロセス内の各スレッドが同時に別のプロセッサで実行され、並列実行が可能になります。
プロセスのスレッド数がプロセッサの数と同じか少ない場合、スレッドサポートシステムとオペレーティング環境の組み合わせにより、各スレッドが異なるプロセッサで確実に実行されます。
たとえば、スレッドとプロセッサの数が同じである行列乗算では、各スレッド(および各プロセッサ)が結果の行を計算します。
さまざまな人々がさまざまな種類の同時実行性と並列性についてさまざまな特定のケースで話しているため、共通の性質をカバーするいくつかの抽象化が必要です。
基本的な抽象化は、同時実行性と並列性の両方がプログラムの特性に起因するコンピュータサイエンスで行われます。ここでは、プログラムはコンピューティングの正式な説明です。このようなプログラムは、特定の言語やエンコーディングである必要はありません。これは、実装固有のものです。API / ABI / ISA / OSの存在は、そのようなレベルの抽象化とは無関係です。確かに、具体的なプログラミング作業を行うには、より詳細な実装固有の知識(スレッドモデルなど)が必要です。基本的な抽象化の背後にある精神は変わりません。
2番目の重要な事実は、一般的な特性として、同時実行性と並列性が多くの異なる抽象化で共存できることです。
一般的な区別として、 並行性と並列性の基本的な見解について関連する回答を参照してください。(いくつかの追加のソースを含むいくつかのリンクもあります。)
並行プログラミングと並列プログラミングは、プログラマビリティを公開する一部のシステムでこのような一般的なプロパティを実装するための手法です。システムは通常、プログラミング言語とその実装です。
プログラミング言語は、組み込みのセマンティックルールによって目的のプロパティを公開する場合があります。ほとんどの場合、このようなルールは特定の言語構造(式など)の評価を指定し、関連する計算を効率的に並行または並列にします。(より具体的には、評価によって暗示される計算効果は、これらの特性を完全に反映できます。)ただし、並行/並列言語のセマンティクスは本質的に複雑であり、実際の作業には必要ありません(効率的な並行/並列アルゴリズムを現実的な問題のソリューションとして実装するため) )。そのため、ほとんどの従来の言語では、より保守的で単純なアプローチを採用しています。評価のセマンティクスを完全に逐次および逐次と仮定し、オプションのプリミティブを提供して、いくつかの計算は並行かつ並列です。これらのプリミティブは、言語でサポートされているキーワードまたは手続き構造(「関数」)にすることができます。これらは、ホストされた環境(OS、または「ベアメタル」ハードウェアインターフェイス)との対話に基づいて実装され、通常は言語に対して不透明(言語を使用して派生させることはできません)です。したがって、プログラマーが見るこの特定の種類の高レベルの抽象化では、これらの「魔法の」プリミティブとこれらのプリミティブに依存するプログラム以外に、並行/並列的なものはありません。プログラマーは、並行性/並列性のプロパティにそれほど関心がない場合でも、プログラミングのエラーが発生しにくい経験を楽しむことができます。
プリミティブは複雑なものを最も高度な抽象化で抽象化しますが、実装には言語機能によって公開されていない余分な複雑さがあります。したがって、いくつかの中間レベルの抽象化が必要です。典型的な例の1つがスレッドです。スレッド化により、1つ以上の実行スレッド(または単にスレッド ;時にはプロセスとも呼ばれます)が可能になります、言語の実装(ランタイム)でサポートされる。これは必ずしもOSでスケジュールされたタスクの概念ではありません)。スレッドは通常、ランタイムによってプリエンプティブにスケジュールされるため、スレッドは他のスレッドについて何も知る必要はありません。したがって、スレッドが何も共有しない限り(重要なリソース)、スレッドは並列処理を実装するのに自然です。):異なるスレッドで計算を分解するだけです。基盤となる実装が実行中に計算リソースのオーバーラップを許可すると、機能します。スレッドは、共有リソースの同時アクセスの影響も受けます。任意の順序でリソースにアクセスするだけで、アルゴリズムに必要な最小限の制約が満たされ、実装はいつアクセスするかを最終的に決定します。このような場合、同期操作が必要になることがあります。一部の言語では、スレッド化と同期の操作を高レベルの抽象化の一部として扱い、それらをプリミティブとして公開します。一方、他の一部の言語では、代わりに比較的高レベルのプリミティブ(futures / promisesなど)のみを推奨します。
言語固有のスレッドのレベルでは、基盤となるホスティング環境(通常はOS)のマルチタスクが発生します。OSレベルのプリエンプティブマルチタスクは、(プリエンプティブ)マルチスレッドを実装するために使用されます。Windows NTなどの一部の環境では、基本的なスケジューリング単位(タスク)も「スレッド」です。上記のスレッドのユーザー空間実装と区別するために、それらはカーネルスレッドと呼ばれます。「カーネル」はOSのカーネルを意味します(ただし、厳密には、これはWindows NTには当てはまりません。「実際の」カーネルはNTです。幹部)。カーネルスレッドは、ユーザースペーススレッドに常に1:1でマッピングされるわけではありませんが、1:1のマッピングでは、マッピングのほとんどのオーバーヘッドが削減されることがよくあります。カーネルスレッドは、作成/破棄/通信するのが重い(システムコールを含む)ため、マッピングのオーバーヘッドを犠牲にしてオーバーヘッドの問題を克服するために、ユーザー空間のグリーンスレッド。高レベルの抽象化で期待されるプログラミングパラダイムに応じたマッピングの選択。たとえば、(Erlangのように)多数のユーザースペーススレッドが同時に実行されることが予想される場合、1:1マッピングは実現不可能です。
OSマルチタスクの基礎は、プロセッサの論理コアによって提供されるISAレベルのマルチタスクです。これは通常、プログラマにとって最も低レベルのパブリックインターフェイスです。このレベルの下に、SMTが存在する可能性があります。これは、ハードウェアによって実装されたより低レベルのマルチスレッドの形式ですが、間違いなく多少プログラム可能です。ただし、通常はプロセッサメーカーのみがアクセスできます。ハードウェア設計は明らかに並列処理を反映していますが、内部ハードウェアリソースを効率的に使用するための同時スケジューリングメカニズムもあります。
上記の「スレッディング」の各レベルでは、並行性と並列性の両方が関係しています。プログラミングインターフェイスは劇的に異なりますが、それらのすべては、最初に基本的な抽象化によって明らかにされたプロパティの影響を受けます。
違いを強調するのに役立つ例を共有するだけです:
並列プログラミング:マージソートアルゴリズムを実装したいとします。問題を2つのサブ問題に分割するたびに、2つのスレッドで問題を解決できます。ただし、マージには両方のサブソリューションが必要なため、マージステップを実行するには、これらの2つのスレッドが完了するのを待つ必要があります。この「強制待機」により、これは並列プログラムになります。
コンカレント・プログラム:セイあなたがしたいn個のテキストファイルを圧縮し、それらのそれぞれの圧縮ファイルを生成します。ファイルのサブセットの圧縮をそれぞれ処理する2(最大n)のスレッドを持つことができます。各スレッドが完了すると、それだけで完了します。待機したり、他に何もする必要はありません。したがって、さまざまなタスクが「任意の順序」で交互に実行されるため、プログラムは並行ですが並列ではありません。
他の誰かが述べたように、すべての並列プログラムは並行しています(実際には並行している必要があります)が、逆ではありません。
私はそれを自分のスタイルで説明しようと思います、それはコンピュータ用語ではないかもしれませんが、それはあなたに一般的な考えを与えます。
例を挙げましょう。家事:食器の掃除、ゴミの出し方、芝刈りなど、3人(スレッド)A、B、Cでやります。
同時: 3人の個人が別々に異なるタスクを開始します。
A --> cleaning dishes
B --> taking out trash
C --> mowing the lawn
ここで、タスクの順序は不確定であり、応答は作業量に依存します
パラレル: ここでは、我々はAは料理とBの洗濯料理ソーピング、2人を割り当てる食器の洗浄、例えば、単一のタスクに複数の人を割り当てることができ、スループット向上させたい場合は可能性があるスループットを向上します。
皿洗い:
A --> soaping the dishes
B --> washing the dishes
など
これがアイデアを与えることを願っています!次に、他の回答で説明されている技術用語に進みます;)