Tech Blog

プログラミングと技術の情報サイト

Pythonでの並列処理・非同期処理の使い分け

Pythonでの並列処理・非同期処理の使い分け

Pythonには並列処理の方法が複数あり、用途によって使い分けが必要です。 GIL(グローバルインタープリタロック)の存在により、 CPUバウンドとI/Oバウンドで最適な手法が異なります。

使い分けの基本方針

  • I/Oバウンド(API呼び出し、DB、ファイル): asyncio または threading
  • CPUバウンド(計算処理、画像処理): multiprocessing

asyncio(非同期I/O)

import asyncio
import aiohttp

async def fetch(url: str) -> str:
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.text()

async def main():
    urls = ["https://api.example.com/1", "https://api.example.com/2"]
    results = await asyncio.gather(*[fetch(u) for u in urls])
    return results

asyncio.run(main())

ThreadPoolExecutor(マルチスレッド)

from concurrent.futures import ThreadPoolExecutor
import requests

def fetch(url):
    return requests.get(url).text

urls = ["https://example.com/1", "https://example.com/2"]
with ThreadPoolExecutor(max_workers=10) as executor:
    results = list(executor.map(fetch, urls))

ProcessPoolExecutor(マルチプロセス)

from concurrent.futures import ProcessPoolExecutor

def heavy_compute(n):
    return sum(i ** 2 for i in range(n))

with ProcessPoolExecutor() as executor:
    results = list(executor.map(heavy_compute, [10**6, 10**6, 10**6]))

まとめ

スクレイピングやAPI並列呼び出しにはasyncioが最も効率的です。 GILの影響を受けるCPU処理はmultiprocessingで別プロセスとして実行しましょう。

← 記事一覧に戻る