Concurrency-in-python-concurrency-vs-parallelism

提供:Dev Guides
移動先:案内検索

並行性と並列性

マルチスレッドプログラムに関しては、並行性と並列性の両方が使用されますが、それらの類似点と相違点については多くの混乱があります。 これに関する大きな問題は、並行性の並列性かどうかです。 両方の用語は非常に似ているように見えますが、上記の質問に対する答えは「いいえ」ですが、並行性と並列性は同じではありません。 今、それらが同じでない場合、それらの間の基本的な違いは何ですか?

簡単に言えば、並行性は異なるスレッドからの共有状態へのアクセスの管理を扱い、反対側は並列処理は複数のCPUまたはそのコアを利用してハードウェアのパフォーマンスを改善することを扱います。

並行性の詳細

同時実行とは、実行時に2つのタスクが重複する場合です。 アプリケーションが複数のタスクで同時に進行している場合があります。 図式的に理解できます。次のように、複数のタスクが同時に進行しています-

同時実行性

並行性のレベル

このセクションでは、プログラミングの観点から並行性の3つの重要なレベルについて説明します-

低レベルの並行性

このレベルの並行性では、アトミック操作の明示的な使用があります。 非常にエラーが発生しやすく、デバッグが難しいため、このような種類の同時実行をアプリケーションの構築に使用することはできません。 Pythonでさえ、このような並行性をサポートしていません。

中レベルの並行性

この並行性では、明示的なアトミック操作の使用はありません。 明示的なロックを使用します。 Pythonおよび他のプログラミング言語は、このような並行性をサポートしています。 ほとんどの場合、アプリケーションプログラマはこの並行性を使用します。

高レベルの並行性

この並行性では、明示的なアトミック操作も明示的なロックも使用されません。 Pythonには、このような種類の同時実行性をサポートする concurrent.futures モジュールがあります。

並行システムのプロパティ

プログラムまたは並行システムが正しいためには、いくつかのプロパティがそれによって満たされる必要があります。 システムの終了に関連するプロパティは次のとおりです-

正確性プロパティ

正しさプロパティは、プログラムまたはシステムが目的の正解を提供する必要があることを意味します。 単純にするために、システムは開始プログラムの状態を最終状態に正しくマッピングする必要があると言えます。

安全性

安全プロパティとは、プログラムまたはシステムが*「良い」または「安全な」状態のままでなければならず、「悪い」*を実行しないことを意味します。

活力プロパティ

このプロパティは、プログラムまたはシステムが「進行」する必要があり、望ましい状態に達することを意味します。

並行システムのアクター

これは、複数のプロセスとスレッドが同時に実行できる並行システムの一般的なプロパティの1つであり、それらは同時に実行されて、独自のタスクを進行させます。 これらのプロセスとスレッドは、並行システムのアクターと呼ばれます。

並行システムのリソース

アクターは、メモリ、ディスク、プリンターなどのリソースを利用する必要があります。 タスクを実行するため。

特定のルールセット

すべての並行システムには、アクターによって実行されるタスクの種類とそれぞれのタイミングを定義する一連のルールが必要です。 タスクには、ロックの取得、メモリ共有、状態の変更などがあります。

並行システムの障壁

データの共有

並行システムを実装する際の重要な問題は、複数のスレッドまたはプロセス間でデータを共有することです。 実際、プログラマーはロックが共有データを保護し、ロックへのすべてのアクセスがシリアル化され、一度に1つのスレッドまたはプロセスのみが共有データにアクセスできるようにする必要があります。 複数のスレッドまたはプロセスがすべて同じ共有データにアクセスしようとすると、少なくとも1つではなくすべてがブロックされ、アイドル状態のままになります。 つまり、ロックが有効になっているときに一度に使用できるプロセスまたはスレッドは1つだけだと言えます。 上記の障壁を取り除くためのいくつかの簡単な解決策があります-

データ共有の制限

最も簡単な解決策は、可変データを共有しないことです。 この場合、明示的なロックを使用する必要はなく、相互データによる並行性の障壁は解決されます。

データ構造支援

多くの場合、並行プロセスは同じデータに同時にアクセスする必要があります。 明示的なロックの使用よりも別の解決策は、同時アクセスをサポートするデータ構造を使用することです。 たとえば、スレッドセーフキューを提供する queue モジュールを使用できます。 マルチプロセッシングベースの同時実行性のために multiprocessing.JoinableQueue クラスを使用することもできます。

不変のデータ転送

並行キューなど、使用しているデータ構造が適切でない場合は、ロックせずに不変データを渡すことができます。

可変データ転送

上記のソリューションの続きとして、不変データではなく可変データのみを渡す必要がある場合、読み取り専用の可変データを渡すことができると仮定します。

I/Oリソースの共有

並行システムを実装する際のもう1つの重要な問題は、スレッドまたはプロセスによるI/Oリソースの使用です。 この問題は、1つのスレッドまたはプロセスがこのような長時間I/Oを使用しており、他のスレッドまたはプロセスがアイドル状態になっている場合に発生します。 I/Oの重いアプリケーションで作業しているときに、このような障壁を確認できます。 これは、Webブラウザーからページを要求する例の助けを借りて理解できます。 重いアプリケーションです。 ここで、データが要求される速度が消費される速度よりも遅い場合、並行システムにI/Oバリアがあります。

次のPythonスクリプトは、Webページを要求し、ネットワークが要求されたページを取得するのにかかった時間を取得するためのものです-

import urllib.request

import time

ts = time.time()

req = urllib.request.urlopen('http://www.finddevguides.com')

pageHtml = req.read()

te = time.time()

print("Page Fetching Time : {} Seconds".format (te-ts))

上記のスクリプトを実行すると、次のようにページ取得時間を取得できます。

出力

Page Fetching Time: 1.0991398811340332 Seconds

ページを取得するのに1秒以上かかることがわかります。 数千の異なるWebページを取得したい場合、ネットワークにどれだけ時間がかかるかを理解できます。

並列処理とは何ですか?

並列処理は、タスクを同時に処理できるサブタスクに分割する技術として定義できます。 上記で説明したように、2つ以上のイベントが同時に発生する並行性とは反対です。 図式的に理解できます。タスクは、次のように、並行して処理できるいくつかのサブタスクに分割されます-

平行度

並行性と並列性の違いについてより多くのアイデアを得るには、次の点を考慮してください-

同時だが並列ではない

アプリケーションは並行することができますが、並行ではない場合、複数のタスクを同時に処理しますが、タスクはサブタスクに分割されません。

並列だが同時ではない

アプリケーションは並列にできますが、同時ではありません。つまり、一度に1つのタスクでのみ動作し、サブタスクに分割されたタスクは並列に処理できます。

並列でも同時でもない

アプリケーションは、並列にも並行にもできません。 つまり、一度に1つのタスクのみで機能し、タスクがサブタスクに分割されることはありません。

並列と同時の両方

アプリケーションは、並行と並行の両方になります。つまり、同時に複数のタスクで動作し、タスクをサブタスクに分割して、それらを並行して実行します。

並列処理の必要性

サブタスクを単一のCPUの異なるコア間、またはネットワーク内で接続された複数のコンピューター間で分散することにより、並列処理を実現できます。

並列性を実現する必要がある理由を理解するには、次の重要な点を考慮してください-

効率的なコード実行

並列処理の助けを借りて、コードを効率的に実行できます。 パーツ内の同じコードが並行して実行されるため、時間を節約できます。

シーケンシャルコンピューティングよりも高速

シーケンシャルコンピューティングは物理的および実用的な要因によって制約されているため、高速なコンピューティング結果を得ることができません。 一方、この問題は並列計算によって解決され、順次計算よりも高速な計算結果が得られます。

実行時間の短縮

並列処理により、プログラムコードの実行時間が短縮されます。

実際の並列処理の例について話すと、コンピューターのグラフィックスカードは、独立して動作し同時に実行できる数百の処理コアを備えているため、並列処理の真の力を強調する例です。 このため、ハイエンドのアプリケーションやゲームも実行できます。

実装するプロセッサの理解

並行性、並列性、およびそれらの違いについては知っていますが、それが実装されるシステムについてはどうでしょうか。 ソフトウェアの設計中に十分な情報に基づいて意思決定を行うことが有益であるため、実装するシステムを理解する必要があります。 次の2種類のプロセッサがあります-

シングルコアプロセッサ

シングルコアプロセッサは、常に1つのスレッドを実行できます。 これらのプロセッサは、*コンテキストスイッチング*を使用して、特定の時間にスレッドに必要なすべての情報を保存し、後で情報を復元します。 コンテキストスイッチングメカニズムは、1秒以内に多数のスレッドを進行させるのに役立ち、システムが複数のことを処理しているように見えます。

シングルコアプロセッサには多くの利点があります。 これらのプロセッサは必要な電力が少なく、複数のコア間に複雑な通信プロトコルはありません。 一方、シングルコアプロセッサの速度は制限されており、大規模なアプリケーションには適していません。

マルチコアプロセッサ

マルチコアプロセッサには、*コア*とも呼ばれる複数の独立した処理ユニットがあります。

各コアには、格納された一連の命令を実行するために必要なものがすべて含まれているため、このようなプロセッサにはコンテキスト切り替えメカニズムは必要ありません。

フェッチ-デコード-実行サイクル

マルチコアプロセッサのコアは、実行サイクルに従います。 このサイクルは Fetch-Decode-Execute サイクルと呼ばれます。 それには、次の手順が含まれます-

フェッチ

これはサイクルの最初のステップで、プログラムメモリからの命令のフェッチが含まれます。

デコード

最近フェッチされた命令は、CPUの他の部分をトリガーする一連の信号に変換されます。

実行する

これは、フェッチおよびデコードされた命令が実行される最終ステップです。 実行結果はCPUレジスタに保存されます。

ここでの利点の1つは、マルチコアプロセッサでの実行がシングルコアプロセッサの実行よりも速いことです。 大規模なアプリケーションに適しています。 一方、複数のコア間の複雑な通信プロトコルは問題です。 マルチコアには、シングルコアプロセッサよりも多くの電力が必要です。