はじめに
「並行」と「並列」はよく混同されやすい概念です。
私自身も以前は違いを明確に説明できませんでした。
今回は両者の違いを解説します。
結論はシンプルですが、前提知識を理解しておくとより納得しやすくなります。
前提知識
CPUコア
CPUコアは、CPU(中央演算処理装置)の中で実際にデータを処理する中核部分です。
論理コア(ハードウェアスレッド)
- 1つの物理コアが同時に複数の命令を処理できる仕組み
- 擬似的なコアで「論理CPU」とも呼ぶ
ソフトウェアスレッド
-
OSが管理する実行の単位 → カーネルスレッド
- 例: Python の
threading.Thread
- 例: Python の
-
ランタイムやライブラリが管理する実行の単位 → ユーザースレッド
- 例: Go の goroutine, Python の asyncio
特にカーネルスレッドを複数作らない場合は 1プロセス = 1カーネルスレッド です。
プロセス
- OSが管理するリソースの単位
- リソース例:
- 仮想メモリ
- ファイルディスクリプタ / ハンドル
- 環境変数
- 各プロセスは独自のリソースを持ち、他のプロセスとは隔離されます
- 1プロセス = 最低1つのカーネルスレッドを持つ
プロセススケジューラー
- CPUを占有し続ける重い処理がある場合、他の処理が実行できなくなる
- そこで タイムスライス によって処理時間を分割し、順番にCPUを割り当てる
- CPU割り当てが終わると、別の待っているスレッドに切り替える(コンテキストスイッチ)
- 処理単位はOSが管理するカーネルスレッド
コンテキストスイッチのタイミング
- タイムスライスの終了
- I/O待ちなどで自発的にCPUを手放した時
並行と並列の違い
| 用語 | 説明 |
|---|---|
| 並行 | 複数の処理を 1つの論理CPU 上で切り替えながら実行し、同時に進行しているように見せる処理 |
| 並列 | 複数の処理(カーネルスレッド単位)を 複数の論理CPU に割り当て、本当に同時に進行させる処理 ※割り込みや論理CPU不足で一部処理は遅れることがある |
並行のイメージ
並列のイメージ
ちなみに
- Python の
threading.Threadはカーネルスレッドを生成する
しかし Python には GIL (Global Interpreter Lock) があり、複数スレッドで同時に Python コードを実行できない、そのため Python のマルチスレッドは「並列」ではなく 並行実行 になります