プロセッサの高速化技術とは?パイプライン・並列処理・マルチプロセッサを基礎から理解しよう
はじめに
CPUは、プログラムに書かれた命令を次々と実行しています。
前回の記事では、命令を、
命令フェッチ
↓
命令デコード
↓
オペランド読出し
↓
命令実行
↓
結果格納
という流れで実行することを学びました。
では、CPUをさらに高速にするにはどうすればよいでしょうか。
単純にクロック周波数を高くするだけではありません。
例えば、
- 複数の命令を流れ作業で処理する
- 複数の命令を同時に実行する
- 複数のプロセッサで処理する
といった方法があります。
この記事では、
プロセッサの高速化
│
├─ パイプライン
│ ├─ パイプライン処理
│ ├─ パイプラインハザード
│ ├─ スーパスカラ
│ └─ VLIW
│
├─ 並列処理
│
├─ マルチプロセッサ
│ ├─ 密結合
│ └─ 疎結合
│
└─ プロセッサ性能
├─ クロック
├─ CPI
├─ MIPS
└─ 実行時間
という流れで学んでいきましょう。
1. プロセッサを高速化するには
CPUの高速化というと、
クロック周波数を上げればいいのでは?
と思うかもしれません。
もちろんクロック周波数も重要です。
しかし、CPUの性能はそれだけでは決まりません。
例えば、
① 1命令を効率よく処理する
② 複数の命令を並行して処理する
③ 複数のプロセッサで処理する
といった方法があります。
その代表的な技術がパイプライン処理です。
2. パイプライン処理
**パイプライン処理(Pipeline Processing)**とは、
命令の処理を複数の段階に分け、複数の命令を並行して処理する方式
です。
工場の流れ作業をイメージすると分かりやすいです。
例えば命令を、
F:命令フェッチ
D:命令デコード
E:実行
の3段階で処理するとします。
パイプラインを使わない場合、
命令1:F → D → E
命令2: F → D → E
命令3: F → D → E
のように、命令1が終わってから命令2を開始します。
これでは各装置に待ち時間が発生します。
3. パイプラインではどうなる?
パイプライン処理では、
時間 → 1 2 3 4 5
命令1 F D E
命令2 F D E
命令3 F D E
のように処理します。
命令1をデコードしている間に、
次の命令2をフェッチ
できます。
さらに命令1を実行している間には、
命令1 → 実行
命令2 → デコード
命令3 → フェッチ
というように、異なる段階で複数の命令を同時進行できます。
4. パイプラインの効果
例えば、
- 1命令を3段階で処理
- 各段階に1クロック必要
- 100命令を実行
するとします。
パイプラインなし
1命令に3クロック必要なので、
3 × 100
= 300クロック
です。
パイプラインあり
最初の命令には3クロック必要ですが、その後は理想的には1クロックごとに命令が完了します。
したがって、
3 + (100 - 1)
= 102クロック
です。
大幅に短縮できます。
5. パイプライン処理の一般式
パイプラインの段数を k、
実行する命令数を n、
各段階の処理時間を t
とすると、理想的なパイプライン処理時間は、
(k + n - 1) × t
と考えられます。
パイプラインを使わなければ、
k × n × t
です。
したがって命令数が多くなるほど、パイプラインの効果が大きくなります。
ただし、これは各段階の処理時間が同じで、途中で待ちが発生しない理想的な場合です。
6. パイプライン処理効果
先ほどの例なら、
段数 k = 3
命令数 n = 100
です。
パイプラインなし:
3 × 100
= 300クロック
パイプラインあり:
3 + 100 - 1
= 102クロック
高速化率を、
高速化率
= 改善前の実行時間 ÷ 改善後の実行時間
で考えると、
300 ÷ 102
≒ 2.94
つまり、約2.94倍高速になったことになります。
命令数を非常に多くすると、理想的な高速化率はパイプラインの段数 k に近づきます。
7. パイプラインハザード
実際のプログラムでは、いつでも理想通りにパイプライン処理できるわけではありません。
パイプライン処理を妨げる問題を、
パイプラインハザード(Pipeline Hazard)
といいます。
代表的には、
- データハザード
- 制御ハザード
- 構造ハザード
があります。
8. データハザード
**データハザード(Data Hazard)**とは、
前の命令の処理結果を、後の命令が必要とすることで発生する問題
です。
例えば、
命令1:A = B + C
命令2:D = A + E
を考えます。
命令2では、命令1で計算する A が必要です。
しかし、
命令1:まだAを計算中
命令2:Aを使いたい!
となると、命令2をそのまま実行できません。
そのため、処理を一時的に待たせる必要があります。
9. 制御ハザード
**制御ハザード(Control Hazard)**は、分岐命令などによって発生します。
例えば、
if 条件:
Aへ移動
else:
Bへ移動
という処理があった場合、
CPUは条件判定が終わるまで、
次にAとBのどちらの命令を実行すればいいのか
確定できません。
そこで利用される高速化技術の一つが、
分岐予測(Branch Prediction)
です。
CPUが、
おそらくこちらへ分岐するだろう
と予測して先に命令を処理します。
予測が当たれば待ち時間を減らせます。
10. 構造ハザード
**構造ハザード(Structural Hazard)**とは、
複数の命令が同じハードウェア資源を同時に使おうとして発生する競合
です。
例えば、
命令1 → メモリを使いたい
命令2 → 同じタイミングでメモリを使いたい
となったとき、両方を同時に処理できない構成なら、一方を待たせる必要があります。
11. パイプラインハザードを整理しよう
| ハザード | 原因 |
|---|---|
| データハザード | 前の命令の結果が必要 |
| 制御ハザード | 分岐先がまだ確定していない |
| 構造ハザード | 同じハードウェア資源を使いたい |
🍯 「データ=結果待ち」「制御=行き先待ち」「構造=装置の取り合い」と覚えると整理しやすいです。
12. スーパスカラ
パイプラインをさらに発展させた高速化技術の一つが、
スーパスカラ(Superscalar)
です。
スーパスカラとは、
複数の実行装置を用意し、複数の命令を同時に実行できるようにする方式
です。
通常のパイプラインでは、理想的には1クロックに1命令ずつ処理を進めます。
スーパスカラでは、
命令1 ─→ 実行装置A
命令2 ─→ 実行装置B
のように、依存関係のない複数の命令を同時に実行できます。
例えば、
A = B + C
D = E + F
なら、この2つに依存関係がなければ並列実行できる可能性があります。
13. スーパスカラのポイント
スーパスカラではCPU側が、
命令を読み出す
↓
依存関係などを調べる
↓
同時実行できる命令を選ぶ
↓
複数の実行装置へ割り当てる
といった制御を行います。
つまり、
どの命令を同時に実行できるかを、主にプロセッサ側で判断する
のがポイントです。
14. VLIW
**VLIW(Very Long Instruction Word)**とは、
同時に実行できる複数の処理を、一つの長い命令語としてまとめる方式
です。
イメージすると、
┌──────────────────────────┐
│ 演算1 │ 演算2 │ 演算3 │ 演算4 │
└──────────────────────────┘
1つの長い命令
となります。
スーパスカラでは、プロセッサ側が命令の依存関係などを調べて並列実行します。
一方、VLIWでは、
どの処理を並列実行するかを主にコンパイラ側であらかじめ決める
という考え方を取ります。
15. スーパスカラとVLIW
| 項目 | スーパスカラ | VLIW |
|---|---|---|
| 並列実行 | 複数命令 | 複数処理を長い命令語に格納 |
| 並列性の判断 | 主にCPU | 主にコンパイラ |
| CPUの制御 | 複雑になりやすい | 比較的単純化しやすい |
| コンパイラの役割 | 通常 | 大きい |
🍯 「スーパスカラ=CPUが並べる」「VLIW=コンパイラが先に並べる」と覚えると違いをつかみやすいです。
16. 並列処理
**並列処理(Parallel Processing)**とは、
複数の処理を同時に実行することで、全体の処理時間を短縮する考え方
です。
例えば100個の仕事を1人で処理するより、
処理A → CPU1
処理B → CPU2
処理C → CPU3
処理D → CPU4
のように複数の処理装置へ分担できれば、高速化が期待できます。
ただし、
CPUを2個にすれば必ず2倍速くなる
わけではありません。
プログラムには、
- 並列化できる処理
- 並列化できない処理
が存在するからです。
17. マルチプロセッサ
**マルチプロセッサ(Multiprocessor)**とは、
複数のプロセッサを利用して処理を行うコンピュータシステム
です。
複数のプロセッサを使うことで、
- 処理性能の向上
- 複数処理の同時実行
- システム全体の能力向上
などを実現できます。
代表的な構成として、
- 密結合マルチプロセッサ
- 疎結合マルチプロセッサ
があります。
18. 密結合マルチプロセッサ
**密結合マルチプロセッサ(Tightly Coupled Multiprocessor)**とは、
複数のプロセッサが主記憶などの資源を共有する構成
です。
CPU1 ─┐
CPU2 ─┼── 共通の主記憶
CPU3 ─┤
CPU4 ─┘
複数のCPUが同じメモリ空間を共有するため、CPU間でデータを共有しやすい特徴があります。
一方で、
- 共有メモリへのアクセス競合
- キャッシュの整合性
- プロセッサ数増加に伴う制御の複雑化
などを考える必要があります。
19. 疎結合マルチプロセッサ
**疎結合マルチプロセッサ(Loosely Coupled Multiprocessor)**とは、
それぞれのプロセッサが独立した主記憶などを持ち、通信路を介して連携する構成
です。
┌─────────┐
│ CPU1 │
│ メモリ1 │
└────┬────┘
│
通信網
│
┌────┴────┐
│ CPU2 │
│ メモリ2 │
└─────────┘
それぞれが比較的独立しているため、システムを拡張しやすい特徴があります。
その一方で、別のプロセッサとデータをやり取りする場合には通信が必要です。
20. 密結合と疎結合
| 項目 | 密結合 | 疎結合 |
|---|---|---|
| 主記憶 | 共有 | 基本的に各プロセッサが個別に持つ |
| CPU間通信 | 共有メモリを利用しやすい | 通信路を利用 |
| 結合 | 強い | 弱い |
| 拡張性 | 規模が大きくなると複雑 | 比較的高い |
21. 並列化で得られる高速化率
並列処理で非常に重要なのが、
処理のすべてを並列化できるわけではない
という点です。
例えばプログラムの、
80% → 並列化できる
20% → 並列化できない
とします。
並列化できる80%を4台のプロセッサで実行すれば、
80% ÷ 4
= 20%
相当の時間になります。
しかし、並列化できない20%はそのまま残ります。
したがって全体の実行時間は、
20% + 20%
= 40%
です。
元の実行時間を100%とすると、
100 ÷ 40
= 2.5
なので、
4プロセッサを使っても高速化率は2.5倍
となります。
22. アムダールの法則
この考え方を一般化したものが、
アムダールの法則(Amdahl's Law)
です。
並列化できる割合を P、
プロセッサ数を N
とすると、高速化率 S は、
1
S = ─────────────────
(1 - P) + P / N
で求められます。
例えば、
P = 0.8
N = 4
なら、
S = 1 / (0.2 + 0.8 / 4)
= 1 / (0.2 + 0.2)
= 1 / 0.4
= 2.5
です。
23. プロセッサを増やし続けたら?
先ほど、
80% → 並列化可能
20% → 並列化不可能
でした。
では、プロセッサ数を無限に増やしたらどうなるでしょうか。
並列部分の処理時間は限りなく0へ近づきます。
しかし、
20%
の逐次処理は残ります。
したがって理論上の最大高速化率は、
1 ÷ 0.2
= 5
です。
つまり、
どれだけプロセッサを増やしても最大5倍
ということになります。
🍯 並列処理では「プロセッサ数」だけでなく「並列化できない部分」が性能の限界を決めます。
24. プロセッサの性能
ここからはCPU性能の計算について見ていきましょう。
重要な用語が、
- クロック周波数
- クロックサイクル時間
- CPI
- MIPS
です。
25. クロック周波数
CPUはクロックと呼ばれる一定周期の信号に合わせて動作します。
**クロック周波数(Clock Frequency)**とは、
1秒間に何回クロックが発生するか
を表します。
単位はHz(ヘルツ)です。
例えば、
1GHz
= 1,000,000,000Hz
= 10^9Hz
なので、
1秒間に10億クロック
です。
26. クロックサイクル時間
1クロックに必要な時間をクロックサイクル時間といいます。
クロック周波数を f とすると、
クロックサイクル時間
= 1 / f
です。
例えば1GHzなら、
1 ÷ 10^9
= 10^-9秒
なので、
1ns(ナノ秒)
です。
27. CPI
**CPI(Cycles Per Instruction)**とは、
1命令を実行するために平均何クロック必要か
を表す値です。
例えば、
CPI = 2
なら、
1命令あたり平均2クロック
という意味です。
CPIが小さいほど、同じクロック周波数なら多くの命令を処理できます。
28. CPUの命令実行時間
CPUがプログラムを実行する時間は、
命令実行時間
= 命令数 × CPI × クロックサイクル時間
で考えられます。
クロックサイクル時間は、
1 / クロック周波数
なので、
命令実行時間
= 命令数 × CPI / クロック周波数
とも表せます。
29. CPU性能の計算例
例えば、
命令数:10億命令
CPI:2
クロック周波数:2GHz
のCPUを考えます。
クロック周波数は、
2GHz = 2 × 10^9Hz
なので、
実行時間
= (10^9 × 2) / (2 × 10^9)
= 1秒
です。
このように、
命令数・CPI・クロック周波数
の3つから実行時間を求められます。
30. MIPS
**MIPS(Million Instructions Per Second)**とは、
1秒間に何百万命令を実行できるか
を表す性能指標です。
例えば、
500 MIPS
なら、
1秒間に5億命令
を実行できるという意味です。
31. クロック周波数とCPIからMIPSを求める
平均CPIが分かっている場合、
1秒あたりの命令数
= クロック周波数 / CPI
です。
例えば、
クロック周波数 = 2GHz
CPI = 4
なら、
2 × 10^9 ÷ 4
= 500 × 10^6
つまり、
500 MIPS
です。
32. クロック周波数だけでは性能を比較できない
例えば、
CPU A
3GHz
CPI = 3
CPU B
2GHz
CPI = 1
とします。
CPU Aは、
3GHz ÷ 3
= 1 × 10^9命令/秒
CPU Bは、
2GHz ÷ 1
= 2 × 10^9命令/秒
です。
この単純化した条件では、
クロック周波数が低いCPU Bのほうが多くの命令を実行できます。
つまり、
GHzが高い=必ず高速
ではありません。
実際のCPU性能は、
- 命令セット
- CPI
- キャッシュ
- パイプライン
- 分岐予測
- コア数
- メモリ性能
- 実行するプログラム
など、多くの要素に左右されます。
33. プロセッサ高速化技術の全体像
今回の内容を整理すると、
プロセッサの高速化
│
├─ 命令を効率よく流す
│ │
│ └─ パイプライン
│ ├─ データハザード
│ ├─ 制御ハザード
│ └─ 構造ハザード
│
├─ 複数命令を同時に実行
│ ├─ スーパスカラ
│ └─ VLIW
│
├─ 複数プロセッサで実行
│ └─ マルチプロセッサ
│ ├─ 密結合
│ └─ 疎結合
│
└─ 性能を評価
├─ クロック周波数
├─ CPI
├─ 実行時間
├─ MIPS
└─ 並列化による高速化率
高速化技術は、
1個のCPUを速くする技術
だけではありません。
命令レベルで並列化する
↓
複数の実行装置を使う
↓
複数のプロセッサを使う
というように、さまざまなレベルで**「同時に処理する」**ことが高速化のポイントになっています。
まとめ
この記事で覚えること
- パイプライン処理は命令処理を複数段階に分けて並行処理する
- 理想的なパイプライン処理時間は
(k + n - 1) × t - パイプラインハザードにはデータ・制御・構造ハザードがある
- スーパスカラは複数の実行装置で複数命令を同時実行する
- スーパスカラでは主にCPUが並列実行する命令を判断する
- VLIWでは主にコンパイラが並列実行する処理を決める
- 並列処理は複数の処理を同時に実行して高速化する
- 密結合マルチプロセッサでは主記憶などを共有する
- 疎結合マルチプロセッサでは各プロセッサが独立した主記憶などを持つ
- プロセッサを増やしても並列化できない部分が残るため、単純に台数分高速になるわけではない
- アムダールの法則から並列化による高速化率を求められる
- クロック周波数は1秒間のクロック数を表す
- CPIは1命令あたりの平均クロック数を表す
- 命令実行時間は
命令数 × CPI ÷ クロック周波数 - MIPSは1秒間に実行できる命令数を100万命令単位で表す
- クロック周波数だけではCPU性能を判断できない
🍯 はちみつメモ
CPU高速化のキーワードは「待たせない・同時にやる」。パイプラインは流れ作業、スーパスカラは作業台を複数用意、マルチプロセッサは作業員そのものを増やすイメージ! ただし作業員を増やしても、1人でしかできない仕事が残ればそこが限界になる。性能計算では「実行時間=命令数×CPI÷クロック周波数」を軸に整理しよう。