【Python】並列処理とfor文

【Python】並列処理とfor文

並列処理とは?

Pythonで大量のデータを処理する際、通常のfor文を使うと逐次実行になり、処理時間が長くなることがあります。並列処理を活用することで、複数の処理を同時に実行し、効率的にタスクを完了させることができます。

threadingを使った並列処理

Pythonの標準ライブラリであるthreadingモジュールを使うと、マルチスレッドを用いた並列処理が可能になります。ただし、PythonのGIL(Global Interpreter Lock)の影響により、CPUバウンドな処理ではあまり効果が得られません。

threadingを使った基本的な例


import threading

def print_number(num):
    print(f"Thread {num} is running")

threads = []
for i in range(5):
    thread = threading.Thread(target=print_number, args=(i,))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

このコードでは、5つのスレッドを作成し、それぞれが異なる番号を出力します。ただし、CPUを多く使用する処理(数値計算など)には適していません。

multiprocessingを使った並列処理

multiprocessingモジュールを使用すると、PythonのGILの制約を回避し、複数のプロセスで処理を並列化できます。CPUバウンドなタスクに適しています。

multiprocessingを使った基本的な例


import multiprocessing

def square(num):
    return num * num

if __name__ == "__main__":
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(square, range(10))
    print(results)

この例では、4つのプロセスを使ってリスト内の数値の二乗を計算しています。CPUバウンドな処理では、multiprocessingを使うことで大幅に高速化できます。

concurrent.futuresを使った並列処理

concurrent.futuresモジュールを使うと、スレッドとプロセスの両方を簡単に管理できます。スレッドプールとプロセスプールのどちらを使うかを選べる点が特徴です。

ThreadPoolExecutorを使った例


from concurrent.futures import ThreadPoolExecutor

def fetch_data(num):
    print(f"Fetching data {num}")
    return num * 2

with ThreadPoolExecutor(max_workers=5) as executor:
    results = list(executor.map(fetch_data, range(10)))

print(results)

ProcessPoolExecutorを使った例


from concurrent.futures import ProcessPoolExecutor

def compute_square(num):
    return num * num

with ProcessPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(compute_square, range(10)))

print(results)

ThreadPoolExecutorはI/Oバウンドなタスクに適し、ProcessPoolExecutorはCPUバウンドなタスクに適しています。

各手法の比較

手法 特徴 適した処理
threading 軽量だがGILの影響を受ける I/Oバウンド(ネットワーク通信、ファイル操作)
multiprocessing プロセス単位で並列処理可能 CPUバウンド(数値計算、大量データ処理)
concurrent.futures スレッドとプロセスを簡単に扱える 汎用的(処理内容に応じて使い分け)

まとめ

Pythonで並列処理を実装する方法として、threadingmultiprocessingconcurrent.futuresの3つがあり、それぞれ適した用途が異なります。用途に応じて最適な手法を選ぶことで、処理の効率を大幅に向上させることができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です