Pythonで並行処理を実装してみた

2024/09/01

Python
並行処理

Pythonで並行処理を実装してみたので使い方をまとめました。

並行処理とは

コンピュータが複数の作業を同時に実行することです。
例えば、YouTubeを視聴しながらプログラムを実行することができるのは、コンピュータが同時に複数の処理をこなしているからです。

マルチスレッドとマルチプロセスの違い

項目 マルチスレッド マルチプロセス
定義 1つのプロセス内で複数のスレッドを並行実行する 複数のプロセスを並行実行する
メモリ空間 スレッドは同じメモリ空間を共有する プロセスごとに独立したメモリ空間を持つ
軽量性 スレッドは軽量で作成や切り替えのコストが低い プロセスは作成や切り替えに高いコストがかかる
安全性 メモリを共有するため、スレッド間の同期や競合管理が必要 独立したメモリ空間で動作するため競合が少ない
スケーラビリティ 同一プロセス内で動作するため、CPUコアを完全に活用できない場合がある 各プロセスが独立して動作し、CPUコアを活用しやすい
使用用途 低コストなタスクを効率的に処理したい場合 (例: Webサーバーでのリクエスト処理) 独立したメモリ空間が必要なタスクや、CPUコアを最大限活用したい場合 (例: 並列計算やデータ処理)

マルチスレッド

multithread.py
from concurrent.futures import ThreadPoolExecutor
import time
from datetime import datetime
import random

def func_multithread(x):
    for n in range(3):
        time.sleep(random.uniform(0.1, 10))
        print(f"func_multithread - {n} ({x})")
    
    return f"result - {x}"

def main():
    print("\n処理開始\n")
    starttime = datetime.now()
    
    with ThreadPoolExecutor(max_workers=4) as executor: # スレッドプールを作成し、最大4つのスレッドで並行処理を実行
        results = executor.map(func_multithread, ["A", "B", "C", "D"]) # リスト内の要素をfunc_multithread関数に渡し、各スレッドで実行
    
    print("\n処理終了\n")
    endtime = datetime.now()

    print(f"実行結果:{list(results)}")

    executiontime = endtime - starttime
    print(f"実行時間:{executiontime}")

if __name__ == "__main__":
    main()
実行結果
処理開始

func_multithread - 0 (D)
func_multithread - 0 (A)
func_multithread - 1 (A)
func_multithread - 1 (D)
func_multithread - 2 (A)
func_multithread - 0 (B)
func_multithread - 1 (B)
func_multithread - 2 (D)
func_multithread - 0 (C)
func_multithread - 2 (B)
func_multithread - 1 (C)
func_multithread - 2 (C)

処理終了

実行結果:['result - A', 'result - B', 'result - C', 'result - D']
実行時間:0:00:19.357473

マルチプロセス

multiprocess.py
from concurrent.futures import ProcessPoolExecutor
import time
from datetime import datetime
import random

def func_multiprocess(x):
    for n in range(3):
        time.sleep(random.uniform(0.1, 10))
        print(f"func_multiprocess - {n} ({x})")
    
    return f"result - {x}"

def main():
    print("\n処理開始\n")
    starttime = datetime.now()
    
    with ProcessPoolExecutor(max_workers=4) as executor: # プロセスプールを作成し、最大4つのプロセスで並列処理を実行
        results = executor.map(func_multiprocess, ["A", "B", "C", "D"]) # リスト内の要素をfunc_multiprocess関数に渡し、各プロセスで実行
    
    print("\n処理終了\n")
    endtime = datetime.now()

    print(f"実行結果:{list(results)}")

    executiontime = endtime - starttime
    print(f"実行時間:{executiontime}")

if __name__ == "__main__":
    main()

実行結果
処理開始

func_multiprocess - 0 (A)
func_multiprocess - 0 (B)
func_multiprocess - 0 (C)
func_multiprocess - 1 (A)
func_multiprocess - 0 (D)
func_multiprocess - 1 (D)
func_multiprocess - 1 (B)
func_multiprocess - 2 (D)
func_multiprocess - 1 (C)
func_multiprocess - 2 (A)
func_multiprocess - 2 (B)
func_multiprocess - 2 (C)

処理終了

実行結果:['result - A', 'result - B', 'result - C', 'result - D']
実行時間:0:00:20.651445

参考

Process PoolExecutorの基本の使い方

今回はここまでです。