TL;DR
並行処理は、プログラムの実行時のパフォーマンスを向上させる。Python で並行処理を実現する方法として、マルチスレッドやマルチプロセスがある。どの方法がベストであるかの判断は、CPU バウンド(数値処理)か I/O バウンド(入出力操作)かによる。
プロセスとスレッド
プログラムが実行されるとき、プロセスが作られ、システムリソース(メモリや CPU)やカーネルのデータ構造が割り当てられる。各プロセスの中には、スレッドが作られ処理が行われる。
プロセスとメモリのイメージ
メモリ
プロセスA
スレッド1→ CPUへ命令
スレッド2→ CPUへ命令
スレッド3→ CPUへ命令
プロセスB
スレッド1→ CPUへ命令
スレッド2→ CPUへ命令
スレッド3→ CPUへ命令
処理の分類
並行性と並列性は、お互いに独立した概念である。
Python 処理 | 意味 | コア数 | スレッド数 |
---|---|---|---|
逐次処理 | 一つずつ順番に実行 | シングルコア | シングルスレッド |
並行処理 | 複数の処理を少しずつ実行 | シングルコア | マルチスレッド |
並列処理 | 複数の処理を同時に実行 | マルチコア | マルチプロセス |
マルチとは複数を示す。
プロセスとは実行中のプログラムのことである。
スレッドとは、OS が CPU に割り当てている最小の実行単位である。プロセスの中に存在し、メモリを共有している。
マルチコアとは、デュアルコア CPU のように、1 チップの CPU 上に複数のコアが存在するもの。人間でいうところの脳が複数あるイメージ。
3 つの処理の違いを簡略化したイメージは次のようになる。右横に進むほど時間が経過する。
逐次処理
1 → 2 → 3
並行処理
1 → 2 → 3
1 → 2 → 3
並列処理
1 → 2 → 3
1 → 2 → 3
1 → 2 → 3
並行処理
「一つの処理を待たずに複数の処理を実行したい」
しかし、一つの CPU しかない場合、どのように複数の処理をすればよいのか?
この問題を解決するために生まれたのが並行処理である。
「我々人間が感知できないような短い間隔で、複数の処理を切り替えながら実行することによって、あたかも、人間が見ると複数の処理が並行しているように見える。」
これが並行処理の考え方である。
Python のプログラムでは、基本的には、並行処理を実装しな限り、常に逐次(ちくじ)処理となる。
マルチプロセス・マルチスレッドを利用する場合は「並行処理」、マルチコアでマルチプロセスを利用する場合は「並列処理」が該当する。
I/O バウンド と CPU バウンド
コンピューターが待機する理由として、次の 2 つがある。
状態 | 発生タイミング | 具体例 |
---|---|---|
CPU バウンド | 数値処理 | 化学計算、暗号化 |
I/O バウンド | 入出力操作 | Web API、DB 接続、ネットワーク通信 |
CPU バウンドな処理であればマルチプロセス、I/O バウンドであればマルチプロセス・マルチスレッドなどが有効である。
同期処理と非同期処理
並行処理に関する用語に、同期処理と非同期処理がある。
簡単に説明すると同期的とは順番に続くこと、非同期とはタスクが独立していることである。
同期処理
同期処理は処理の完了まで次に進めない。例えば、Python の場合、関数を呼び出したとき、呼び出し先の処理が全て完了するまで、呼び出し元は次の処理に進めない。
非同期処理
一方、非同期処理は、呼び出し先の処理が実行中であっても、呼び出し元は次の処理に進める。呼び出した先の結果が返る前であっても呼び出し元は先に進んでいるので、結果はコールバック関数(関数に渡される関数)を利用して、呼び出し元に伝えられる。このとき、並行処理である。
Python においてスレッドやマルチプロセスを扱う場合は、細部に注意が必要だ。この作業を単純化するために、Python 公式ドキュメントでは、コードの並行実行のサポートを提供している。並行処理を扱うものでは、concurrent.futures モジュールがある。このモジュールの詳細については、別のページで解説する。
並行実行のライブラリ一覧 — Python 3.10.0b2 ドキュメント
並列処理
複数のコアを使って同時に複数の計算を行うことを、並列処理という。物理的に同時に処理が行われている。
様々な処理が、物理的に同時進行しているパラレルワールドをイメージするとよい。
並列処理は、マルチコア(複数のコア)でマルチプロセス(複数のプロセス)を利用する場合である。マルチコアでは、同時に複数の計算ができる。各コアは独立しているから、それぞれのコアは他のコアに影響されることなく動作する。
CPU コアが 1 つだけの場合、並列処理というのはありえないということになる。デュアルコアの場合は、一つの CPU に 2 個のコアが存在するので並列処理が可能である。