プログラミングをしているとよく出てくるこの3つ:
- プロセス
- スレッド
- CPUコア(物理・論理)
なんとなく分かっているけど、「実際どう動いてるの?」が曖昧になりがちです。
この記事では、以下の図をベースにして直感的に理解していきます。
CPU物理構造
│
├─ 物理コア1 ── 論理スレッド#0, #1
├─ 物理コア2 ── 論理スレッド#2, #3
...
├─ 物理コア16 ── 論理スレッド#30, #31
OSスケジューラ
│
├─ PythonプロセスA(PID 1234)
│ ├─ Thread-1 → 論理スレッド#5
│ └─ Thread-2 → 論理スレッド#12
│
└─ PythonプロセスB(PID 5678)
├─ Thread-1 → 論理スレッド#9
├─ Thread-2 → 論理スレッド#18
└─ Thread-3 → 論理スレッド#27
1. CPUの「8コア16スレッド」って何?
まずハードウェア側の話。
■ 物理コア
実際の計算装置(脳みそ)
- 8コア → 8個の独立した処理ユニット
■ 論理スレッド(ハイパースレッディング)
1つの物理コアを2つの処理単位として見せる仕組み
- 8コア16スレッド =
8物理コア × 2論理スレッド
👉 OSから見ると「16個のCPUがあるように見える」
2. プロセスとは?(←ここが誤解ポイント)
■ 定義
「実行中のプログラム」
…なんだけど、ここが重要👇
👉 プロセス自体はCPUで直接動かない“概念的な箱”
図では:
PythonプロセスA(PID 1234)
PythonプロセスB(PID 5678)
■ イメージ
👉 プロセスは“存在しているだけ”では何も実行しない
👉 スレッドが初めてCPU上で命令を実行する
- プロセス = メモリ空間 + リソースの入れ物
- スレッドを中に持っている
👉 「実行主体ではなく、実行環境」
■ 特徴
- メモリ空間が分離されている(安全)
- 他のプロセスと基本的に直接干渉できない
3. スレッドとは?(実際に動くやつ)
■ 定義
「プロセスの中の実行単位」
プロセスA
├─ Thread-1
└─ Thread-2
■ ここが一番重要
👉 CPUで実際に動くのはスレッドだけ
- プロセスは直接CPUに乗らない
- スレッドがCPUにスケジュールされる
■ 特徴
- 同じメモリを共有
- 軽い(生成コストが低い)
- 競合(レースコンディション)が起きる
4. OSスケジューラの役割
■ OSスケジューラとは?
「どの“スレッド”をどのCPUで動かすか決めるやつ」
図のこの部分👇
Thread-1 → 論理スレッド#5
Thread-2 → 論理スレッド#12
👉 プロセスではなくスレッドが割り当て対象
5. 実際の実行イメージ
PythonプロセスA
├─ Thread-1 → CPU#5
└─ Thread-2 → CPU#12
PythonプロセスB
├─ Thread-1 → CPU#9
├─ Thread-2 → CPU#18
└─ Thread-3 → CPU#27
■ 本質
👉 スレッドがCPUに乗る
👉 プロセスはそのスレッドを入れている箱
6. 並列 vs 並行
■ 並列(Parallel)
複数コアで同時実行
👉 スレッドが別コアに乗る
■ 並行(Concurrency)
1つのコアを時間分割
👉 スレッドを切り替えてるだけ
7. Pythonでの注意(重要)
■ GIL(Global Interpreter Lock)
👉 1プロセス内では同時に1スレッドしかCPU実行できない(CPUバウンド時)
つまり:
- スレッドは複数あっても
- 実際にCPUで動くのは1つずつ
8. まとめ(ここだけ覚えればOK)
| 概念 | 正体 |
|---|---|
| CPUコア | 実際に計算する物理装置 |
| 論理スレッド | OSから見えるCPU単位 |
| プロセス | 実行環境(箱・概念) |
| スレッド | 実行主体(CPUに乗る) |
| OSスケジューラ | スレッドをCPUに割り当てる |
9. 一言でいうと
👉 「プロセスは箱、スレッドが本体」
👉 CPUで動くのは常にスレッドだけ
10. よくある誤解
❌ プロセスがCPUで動く
→ 実際に動くのはスレッド
❌ スレッド = CPUのスレッド
→ 全く別物(ソフト vs ハード)
❌ コア数×2が最適スレッド数
→ ワークロード次第
さいごに
Pythonのスレッド、プロセスが実際にどう動くのか気になったので調べてまとめてみました。