Python における並列処理は、プログラムが複数のタスクを同時に実行できるようにする技術であり、それによって全体的なパフォーマンスが向上します。Python には、スレッド化、マルチプロセッシング、concurrent.futures モジュールなど、並列処理を実現するためのいくつかの方法が用意されています。このブログ投稿では、スレッドとプロセスの概念、それらの違い、およびそれらを選択する場合について説明します。また、Python での並列コンピューティングへの高レベル インターフェイスとして concurrent.futures モジュールも紹介します。並列コンピューティングにスレッド、プロセス、concurrent.futures を使用する方法を説明する例を示します。
糸
スレッド (Thread) は、プログラム内の単一の制御フローを表す最小の実行単位です。これらは、オペレーティング システムが管理およびスケジュールできる実行の最小単位です。プロセス内のスレッドは、メモリやファイル ハンドルなどの一部のリソースを共有するため、複数のスレッド間でのデータ共有がより簡単かつ効率的になります。ただし、これは、競合状態やデッドロックなどの問題を回避するために、共有データに安全にアクセスし、適切に同期するように注意する必要があることも意味します。
Python では、スレッド モジュールを使用してスレッドを作成および管理できます。以下に例を示します。
import threading
def print_numbers():
for i in range(5):
print(f'Number {i}')
def print_letters():
for letter in 'abcde':
print(f'Letter {letter}')
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
Python の CPython 実装には、スレッドの並列実行を制限するグローバル インタープリター ロック (Global Interpreter Lock、GIL) があることに注意してください。これにより、スレッドは Python の IO 集中型タスクにより適したものになります。つまり、スレッドは主に IO 操作が完了するまで待機することになります。
プロセス
プロセス(プロセス)はスレッドとは異なり、完全に独立したメモリ空間を持ち、独自の独立した環境で動作します。これは、プロセス間通信にはより複雑なメカニズムが必要であり、スレッド通信に比べて速度が遅くなる可能性があることを意味します。ただし、プロセスはより適切に分離されており、あるプロセスのバグやクラッシュが他のプロセスに影響を与えることはありません。
Python のマルチプロセッシング モジュールは、プロセスの作成と管理に使用されます。以下に例を示します。
from multiprocessing import Process
def print_numbers():
for i in range(5):
print(f'Number {i}')
def print_letters():
for letter in 'abcde':
print(f'Letter {letter}')
process1 = Process(target=print_numbers)
process2 = Process(target=print_letters)
process1.start()
process2.start()
process1.join()
process2.join()
プロセスは真の並列処理を実現できるため、Python での CPU 負荷の高いタスクにはマルチプロセッシングがより適しています。つまり、タスクを同時に実行するとパフォーマンスが大幅に向上します。
同時先物
concurrent.futures モジュールは、Python で呼び出し可能なオブジェクトを非同期に実行するための高レベルのインターフェイスを提供します。これには、複数のスレッドまたはプロセスをそれぞれ使用してコード実行を並列化するための ThreadPoolExecutor クラスと ProcessPoolExecutor クラスがあります。このモジュールは、スレッドとプロセスを管理するプロセスを簡素化し、例外の処理や利用可能な結果との対話などの追加機能を提供します。
concurrent.futures.ThreadPoolExecutor を使用した使用例:
from concurrent.futures import ThreadPoolExecutor
def square(x):
return x * x
with ThreadPoolExecutor(max_workers=4) as executor:
result = list(executor.map(square, range(0, 10)))
print(result)
concurrent.futures.ProcessPoolExecutor を使用した使用例:
from concurrent.futures import ProcessPoolExecutor
def square(x):
return x * x
with ProcessPoolExecutor(max_workers=4) as executor:
result = list(executor.map(square, range(0, 10)))
print(result)
スレッドとプロセス: 違いの概要
- メモリとリソースの共有
- 作成して管理する
- 同時実行性と並列処理
- エラー処理と許容範囲
これらの違いの詳細については、このブログ投稿の前半で説明した詳細な説明を参照してください。
スレッド、プロセス、または concurrent.futures をいつ使用するか
スレッドまたはプロセスの選択は、実行されるタスクの特定の要件と性質によって異なります。
IO 操作が完了するまで複数のタスクが待機する必要があることが多い IO 集約型タスクの場合は、スレッドを使用できます。スレッドは軽量で、メモリとリソースを共有し、IO 集中型の同時タスクのパフォーマンスを向上させます。concurrent.futures.ThreadPoolExecutor を使用すると、スレッド管理を簡素化できます。
計算効率を最大限に高めるために真の並列処理が必要な、CPU を大量に使用するタスクの場合は、プロセスを使用できます。このプロセスは重量があり、分離されており、耐障害性が優れています。concurrent.futures.ProcessPoolExecutor を使用すると、プロセス管理を簡素化できます。
結論は
このブログ投稿では、Python のスレッドとプロセスの概念を調査し、それらの違いについて説明し、並列コンピューティングへの高レベルのインターフェイスとして concurrent.futures モジュールを紹介します。効率的な Python プログラムを作成するには、スレッド、プロセス、または concurrent.futures をいつ使用するかを知ることが重要であり、アプリケーションのパフォーマンスを大幅に向上させることができます。
スレッドとプロセスの間、または concurrent.futures の ThreadPoolExecutor と ProcessPoolExecutor の間で選択する場合は、タスク タイプ (CPU 集中型または IO 集中型)、利用可能な CPU コアの数、同時実行性、並列処理、および同期要件を考慮することを忘れないでください。これらの要素を念頭に置いて、Python プログラムに最適な並列処理方法を選択し、パフォーマンスを最適化できます。
読む
読む
AIの書籍リスト
AIは日々変化していますが、高層ビルは良好な基礎から切り離すことはできません。人工知能の原理と実践について学ぶことに興味がありますか? これ以上探さない!AI の原則と実践に関する書籍は、AI の世界について詳しく知りたい人にとって最適なリソースです。この分野の第一線の専門家によって書かれたこの包括的なガイドは、機械学習の基礎からインテリジェント システムを構築するための高度なテクニックまですべてをカバーしています。初心者であろうと経験豊富な AI 実践者であろうと、この本はあなたをカバーします。では、なぜ待つのでしょうか?
人工知能の原理と実践は、人工知能とデータ サイエンスのさまざまな重要なシステムの古典を包括的にカバーしています。
北京大学出版局、人工知能の原理と実践 人工知能とデータ サイエンスの入門から熟練度まで 機械学習ディープ ラーニング アルゴリズムの原理の詳細な説明