ホームページ >バックエンド開発 >Python チュートリアル >Pythonマルチプロセスと並列プログラミングのガイド
計算をスピードアップすることは、誰もが達成したい目標です。現在の実行時間よりも10倍速く実行できるスクリプトがある場合はどうなりますか?この記事では、Python MultiprocessingとMultiProcessingと呼ばれるライブラリを見ていきます。並列プログラミングを使用して、マルチプロセッシングが何であるか、その利点、およびPythonプログラムの実行時間を改善する方法について説明します。
わかりました、行こう!キーテイクアウト
並列およびシリアルコンピューティング
あなたが解決すべき大きな問題を抱えていると想像してください、そしてあなたは一人です。 8つの異なる数値の平方根を計算する必要があります。職業はなんですか?まあ、あなたには多くの選択肢がありません。最初の番号から始めて、結果を計算します。次に、他の人と一緒に行きます。
あなたがあなたを助けてくれる数学が得意な3人の友達がいるとしたら?それらのそれぞれは2つの数値の平方根を計算し、仕事の負荷は友達の間で均等に分配されるため、仕事は簡単になります。これは、問題がより速く解決されることを意味します
わかりました、すべて明確ですか?これらの例では、各友人はCPUのコアを表しています。最初の例では、タスク全体があなたによって連続的に解決されます。これはシリアルコンピューティングと呼ばれます。 2番目の例では、合計4つのコアを使用しているため、並列コンピューティングを使用しています。並列コンピューティングには、プロセッサ内の複数のコア間で分割される並列プロセスまたはプロセスの使用が含まれます。
並列プログラミングのモデル
完全に平行。タスクは独立して実行でき、互いに通信する必要はありません。
共有メモリの並列性。プロセス(またはスレッド)が通信する必要があるため、グローバルアドレス空間を共有します。
最初の利点はパフォーマンスに関連しています。 Multiprocessingは新しいプロセスを作成するため、タスクを他のコアに分割することにより、CPUの計算能力をよりよく使用できます。ほとんどのプロセッサは最近のマルチコアプロセッサであり、コードを最適化する場合は、計算を並行して解決することで時間を節約できます。 2番目の利点は、マルチスレッドであるマルチプロセスの代替手段を調べます。ただし、スレッドはプロセスではなく、これに結果が生じます。スレッドを作成する場合、通常のプロセスで行うように、スレッドを殺したり、中断することも危険です。マルチプロセッシングとマルチスレッドの比較はこの記事の範囲内ではないため、さらに読むことをお勧めします。
マルチプロセッシングの3番目の利点は、処理しようとしているタスクが並列プログラミングに適していることを考えると、実装が非常に簡単であることです。Python Multiprocessing
を開始しますついにPythonコードを書く準備ができています!
親プロセス。複数の子供を持つことができる親のプロセスは1つだけです。
子プロセス。これは親によって生まれました。各子供には新しい子供もいることもあります。
プロセスクラス
ターゲット= bubble_sort、つまり、新しいプロセスがbubble_sort関数を実行することを意味します
<span>from multiprocessing import Process </span> <span>def bubble_sort(array): </span> check <span>= True </span> <span>while check == True: </span> check <span>= False </span> <span>for i in range(0, len(array)-1): </span> <span>if array[i] > array[i+1]: </span> check <span>= True </span> temp <span>= array[i] </span> array<span>[i] = array[i+1] </span> array<span>[i+1] = temp </span> <span>print("Array sorted: ", array) </span> <span>if __name__ == '__main__': </span> p <span>= Process(target=bubble_sort, args=([1,9,4,5,2,6,8,4],)) </span> p<span>.start() </span> p<span>.join() </span>
args =([1,9,4,52,6,8,4]、)、これはターゲット関数への引数として渡される配列
出口を終える前に、子どものプロセスが計算を終了するのを待つ必要があります。 Join()メソッドは、プロセスが終了するのを待ちますこの例では、1つの子プロセスのみを作成しました。ご想像のとおり、プロセスクラスでより多くのインスタンスを作成することで、より多くの子プロセスを作成できます。
プールクラス
このコードスニペットでは、単に整数を採取して平方根を返すキューブ(x)関数があります。簡単ですよね?
次に、属性を指定せずにプールクラスのインスタンスを作成します。プールクラスは、デフォルトでCPUコアごとに1つのプロセスを作成します。次に、いくつかの引数でMAPメソッドを実行します。
<span>from multiprocessing import Process </span> <span>def bubble_sort(array): </span> check <span>= True </span> <span>while check == True: </span> check <span>= False </span> <span>for i in range(0, len(array)-1): </span> <span>if array[i] > array[i+1]: </span> check <span>= True </span> temp <span>= array[i] </span> array<span>[i] = array[i+1] </span> array<span>[i+1] = temp </span> <span>print("Array sorted: ", array) </span> <span>if __name__ == '__main__': </span> p <span>= Process(target=bubble_sort, args=([1,9,4,5,2,6,8,4],)) </span> p<span>.start() </span> p<span>.join() </span>マップメソッドは、私たちが提供する反復可能なすべての要素にキューブ関数を適用します。この場合、10からNのすべての数字のリストです。
これの大きな利点は、リストの計算が並行して行われていることです!
Python Multiprocessingを最大限に活用
複数のプロセスを作成し、並列計算を行うことは、必ずしもシリアルコンピューティングよりも効率的ではありません。 CPU集約型タスクが低い場合、シリアル計算は並列計算よりも高速です。このため、マルチプロセッシングをいつ使用するかを理解することが重要です。これは、実行しているタスクに依存します。
これを納得させるには、簡単な例を見てみましょう:
ご覧のとおり、1秒以上の違いがあります。したがって、この場合、マルチプロセッシングの方が優れています
Nの値のようにコードの何かを変更しましょう。n = 10000に下げて、何が起こるかを見てみましょう。<span>from multiprocessing import Pool </span><span>import time </span><span>import math </span> N <span>= 5000000 </span> <span>def cube(x): </span> <span>return math.sqrt(x) </span> <span>if __name__ == "__main__": </span> <span>with Pool() as pool: </span> result <span>= pool.map(cube, range(10,N)) </span> <span>print("Program finished!") </span>これが私が今得ているものです:
何が起こったのですか?マルチプロセッシングは今では悪い選択であるようです。なぜ?
<span>from multiprocessing import Pool </span><span>import time </span><span>import math </span> N <span>= 5000000 </span> <span>def cube(x): </span> <span>return math.sqrt(x) </span> <span>if __name__ == "__main__": </span> <span># first way, using multiprocessing </span> start_time <span>= time.perf_counter() </span> <span>with Pool() as pool: </span> result <span>= pool.map(cube, range(10,N)) </span> finish_time <span>= time.perf_counter() </span> <span>print("Program finished in {} seconds - using multiprocessing".format(finish_time-start_time)) </span> <span>print("---") </span> <span># second way, serial computation </span> start_time <span>= time.perf_counter() </span> result <span>= [] </span> <span>for x in range(10,N): </span> result<span>.append(cube(x)) </span> finish_time <span>= time.perf_counter() </span> <span>print("Program finished in {} seconds".format(finish_time-start_time)) </span>プロセス間で計算を分割することで導入されたオーバーヘッドは、解決されたタスクと比較して大きすぎます。時間のパフォーマンスの観点からどれほどの違いがあるかを見ることができます。
結論
この記事では、Python Multiprocessingを使用して、Pythonコードのパフォーマンスの最適化について説明しました。
最初に、並列コンピューティングとは何か、それを使用するための主要なモデルを簡単に紹介しました。次に、マルチプロセッシングとその利点について話し始めました。最終的に、計算を並列化することが常に最良の選択ではないことがわかり、マルチプロセッシングモジュールはCPUバウンドタスクの並列化に使用する必要があることがわかりました。いつものように、それはあなたが直面している特定の問題を考慮し、異なる解決策の長所と短所に評価することの問題です。
私と同じように便利なPythonマルチプロセッシングについて学ぶことを見つけたことを願っています。 Pythonマルチプロセッシングと並列プログラミングに関するFAQPythonでマルチプロセッシングを使用することの主な利点は何ですか?
マルチプロセッシングモジュールの共有メモリメカニズムを使用して、Pythonのプロセス間でデータを共有できます。これらには、それぞれ共有変数と配列を作成できる値クラスとアレイクラスが含まれます。ただし、各プロセスには独自のメモリ空間があるため、1つのプロセスで共有変数または配列に変更された変更は、マルチプロセッシングモジュールによって提供されるロックまたは他の同期プリミティブを使用して明示的に同期しない限り、他のプロセスに反映されないことに注意することが重要です。
Pythonでマルチプロセッシングプログラムをデバッグするのは困難な場合があります。ただし、プログラムをデバッグするために使用できる手法がいくつかあります。 1つの方法は、印刷ステートメントまたはロギングを使用してプログラムの実行を追跡することです。別の方法は、PDBモジュールのset_trace()関数を使用して、コード内のブレークポイントを設定することです。また、マルチプロセスモジュールのlog_to_stderr()関数など、マルチプロセッシングをサポートする専門のデバッグツールを使用することもできます。これにより、プロセスのアクティビティを標準エラーにログに記録できます。オペレーティングシステム?
- プロセスクラスのJoin()メソッドを呼び出すことで、常にプロセスをクリーンアップします。 。
- プログラムが予期せずクラッシュするのを防ぐために例外を適切に処理します。以上がPythonマルチプロセスと並列プログラミングのガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。