記事の背景
最近、スクレイピングタスクで非同期処理を用いたことで処理時間が劇的に短縮することができました。改めて「並列処理・並行処理」「同期・非同期処理」「マルチスレッド・マルチプロセス」「I/Oバウンド・CPUバウンド」について知識を整理したくなったので、この記事ではそれらを料理🍳に例えながらわかりやすく解説します。
目次
1. 並列処理と並行処理の違い
並列処理
- 複数の処理を同時に実行すること。
- 例: 4コアCPUで4つのタスクを同時に処理する。
並行処理
- 複数の処理が同時期に進行しているが(見かけ上は並列に見える)、厳密には1つのCPUコアがタスクを交互に高速で切り替えながら処理している。
- 例: 1コアCPUが複数のタスクを切り替えて効率よく進める。
料理に例えると🍳
-
並列処理
2人の料理人が別々の料理を同時に作る。 -
並行処理
1人の料理人が複数の料理を並行して作る。片方を煮込んでいる間に、もう片方を焼く。
2. 同期処理と非同期処理の違い
同期処理 (Synchronous Processing)
- 一つのタスクが完了するまで次のタスクが実行されない。
- タスクが順番に実行されるため、処理の流れが分かりやすい。
- 例:ファイルを読み込んでからデータを処理するまで待つ処理。
非同期処理 (Asynchronous Processing)
- 処理が完了するのを待たずに次の処理に進む方法です。
- JavaScriptでは
setTimeout
,Promise
,async/await
などが非同期処理の代表例です。 - 例:APIリクエストを送り、レスポンスを待っている間に他の処理を行う。
料理に例えると🍳
-
同期処理
- 一人のシェフが一つの料理を作る。
- シェフは、野菜を切ってから炒め、その後に煮込み、すべての手順が終わるまで次の料理に取り掛からない。
- 料理が一つずつ順番に仕上がるため、わかりやすいが時間がかかる。
-
非同期処理
- シェフが複数の料理を同時に進める。
- 野菜を切り終えたら煮込みが終わるのを待たずに次の料理の準備を始める。
- 煮込みが終わるまでの間に他の料理が進むため、効率が良いが、タイミング管理が必要。
3. マルチスレッドとマルチプロセスの違い
マルチスレッド (Multi-threading)
- 一つのプロセス内で複数のスレッドを動かし並行処理を行う。
- メモリ共有が可能。
- スレッド間のデータ共有が容易だが、競合の管理が必要。
マルチプロセス (Multi-processing)
- 複数のプロセスを作成し、それぞれが独立して動作。
- メモリ共有が難しいが、安定性が高い。
- プロセス間通信 (IPC) でデータをやり取りする必要がある。
料理に例えると🍳
-
マルチスレッド
- キッチンで一人のシェフが複数の料理を同時に調理する。
- 一人のシェフ(プロセス)が複数の手(スレッド)を使い、同時に複数の料理を作る。
- ただし、キッチン(メモリ)を共有するため、他の料理との取り合い(競合)が発生する可能性がある。
-
マルチプロセス
- 複数のシェフがそれぞれ別の料理を同時に調理する。
- それぞれのシェフ(プロセス)が独自のキッチン(メモリ)を持っており、他のシェフと干渉しない。
- 独立して動作するため、効率は高いがコミュニケーション(プロセス間通信)が必要な場合は少し手間がかかる。
4. I/OバウンドとCPUバウンドの違い
I/Oバウンド
- 入出力処理 (ネットワーク通信、ファイル操作など) がボトルネック。
- 非同期処理が効果的。
- 処理待ち時間が多いため、スレッドがブロックされない非同期設計が適している。
CPUバウンド
- CPUの計算処理がボトルネック。
- 並列処理 (マルチプロセスやマルチスレッド) が効果的。
- 処理速度はコア数に依存し、スレッドやプロセスを分散して並列実行するのが最適。
料理で例えると
-
I/Oバウンド
- 野菜を切った後に鍋で煮込む。煮込みが終わるのを待っている間は他の作業ができないため、手持ち無沙汰になる。
- I/Oバウンドはこの煮込みの時間のように、処理待ちが発生する。
-
CPUバウンド
- 全ての工程が包丁での細かい作業 (みじん切りなど) で、シェフがずっと手を動かし続ける必要がある。
- CPUバウンドはこのように計算や処理自体が重く、他の作業を並行して行う余裕がない状態。
5. 技術選定の参考基準
処理の種類 | マルチプロセス | マルチスレッド | 非同期処理 |
---|---|---|---|
スケールのしやすさ | △ (CPUコア数に依存) | ○ (メモリ内でスレッド増加可能) | ◎ (I/O待ち時間に強い) |
I/Oバウンド向き | ○ (プロセス間の通信が必要) | ○ (スレッド間でリソース競合) | ◎(イベントループで効率的) |
CPUバウンド向き | ◎ (各プロセスが独立して動作) | △ (スレッド切り替えがオーバーヘッドに) | △ (シングルスレッドなので向かない) |
リソース競合の少なさ | ◎ (プロセス間で分離) | △ (共有メモリの競合あり) | ◎ (独立した処理が可能) |
設計の簡単さ | △ (プロセス間通信が必要) | ○ (スレッド内で通信可能) | ◎ (非同期関数で簡潔に記述可能) |
用途 | 重い計算タスク、データ分析 | 画像処理や動画編集などの並列作業 | Webサーバー、スクレイピング |