よんログ

コンピュータアーキテクチャ

プロセッサを構成する素子の変遷

  1. 真空管
  2. トランジスタ
  3. 集積回路 (IC, Integrated Circuits, LSI, Large Scale Integration)
  4. 大規模集積回路 (VLSI, Very Large Scale Integration)

ムーアの法則

ムーアの法則 (Moore's law) とは、集積回路当たりに実装できる素子数が18ヶ月で2倍になるという予測であり、後に法則となった。

命令アーキテクチャ

CISCとはRISC

命令アーキテクチャの設計アプローチにはCISC (Complex Instruction Set Computer)RISC (Reduced Instruction Set Computer) の2つに分けられる。

CISCは複雑な命令を極力一命令で実現させる設計アプローチである。 反対に、RISCは単純な命令のみを命令セットに含める設計アプローチである。

アプローチハードウェアの構造命令数一命令当たりの実行時間
CISC複雑多い遅い
RISC単純少ない早い

RISCを採用したプロセッサではプログラムが単純な命令のみで構成されるため、命令数は多くなる。 しかし、命令が固定長でありハードウェア構造が比較的単純であることから、最適化がしやすい。 (後述のマイクロアーキテクチャ参照)

マイクロアーキテクチャ

スーパースカラ

スーパースカラ (superscalar) は、クロックサイクル毎に複数の命令を読みそれらを複数のユニットを使って処理することで1サイクル当たりの並列実行命令数を増やす、プロセッサの最適化手法の一つである。

パイプライン処理

プロセッサの命令は以下のステージに細分化することができる。 (ただし、プロセッサはRISCを採用しているとする)

内部処理略称内容利用する機能ユニット
命令フェッチIF (Instruction Fetch)メモリあるいは命令キャッシュから命令を読むフェッチユニット
命令デコードID (Instruction Decode)命令を解釈するデコードユニット
オペランドRR (Register Read)命令の実行に必要なオペランド (operand, 演算の対象) をレジスタから読むレジスタファイル
メモリアクセスMA (Memory Access)メモリを読み書きするロード/ストアユニット
実行EX (EXecute)指定された演算を行う演算ユニット
レジスタへのライトバックWB (Write Back)演算結果をレジスタに書くレジスタファイル

処理中の命令の終了を待って次の命令の処理を開始するのでは、機能ユニットが遊んでいるサイクルが発生してしまう。 そこで、それぞれの機能ユニットの処理結果をレジスタに格納し次のサイクルには次の命令の処理を始めることで、順次実行するより性能向上が期待できる。 この方式をパイプライン (pipeline) 処理方式という。

命令パイプラインのイメージ

クロックサイクル/命令No12345678
1IFIDRREXMAWB
2IFIDRREXMAWB
3IFIDRREXMAWB
4IFIDRREXMA

パイプラインハザード

プログラマがプログラムを書くとき、命令は順序通りに一つ一つ実行されることを期待する。 前述のパイプライン処理を行う場合と逐次実行した場合で結果が異なるような場合、それを回避するために命令パイプラインへの命令の投入を中断せざるを得ない状況が生じうる。 このような状況をパイプラインハザード (pipeline hazard) という。 パイプラインハザードには以下の3つに分類される。

構造ハザード

他の命令とのハードウェア資源の競合が発生し、一方の命令がもう一方を待つことによるハザード。

データハザード

ある命令のオペランドがその前の命令の演算結果であり、前の命令の処理完了を待つことによるハザード。

制御ハザード

分岐条件の成立/不成立で処理を分岐する場合、条件が評価されるまで分岐先の命令をフェッチできないことによるハザード。

また、命令パイプライン中の命令を実行できないステージをパイプラインバブル (pipeline bubble) という。

Out-of-Order実行

Out-of-Order実行は、プログラムにおける命令の実行順序に依らず、処理可能な (オペランドが揃っている) 命令から逐次実行することでプログラムの並列性を向上させる、プロセッサの最適化手法の一つである。

データの依存関係

Out-of-Order実行では、命令の実行順序を変更しても逐次実行したときと同じ結果が得られることを保証しなければならない。

しかし、命令間のデータ依存によって、命令の実行順序を変更できない場合がある。 具体的には、命令間のデータ依存は以下の3つの分けられる。

逆依存
ある命令がその前の命令で読んだレジスタに書き込むような状況。
出力依存
ある命令がその前の命令で書き込んだレジスタに再び書き込むような状況。
フロー依存

ある命令のオペランドがその前の命令の演算結果であるような状況。 (パイプライン処理のデータハザード)

レジスタリネーム

レジスタリネーム (register renaming) は、逆依存あるいは出力依存の依存関係をもつ命令間において、それぞれ別々のレジスタを割り当てることでデータハザードを解消する、プロセッサの最適化手法の一つである。

リザベーションステーション

リザベーションステーション (reservation station) は、Out-of-Order実行において命令の実行順序を変更しても逐次実行したときと同じ結果が得られることを保証するため、命令のデータ依存 (フロー依存) を管理する。

デコードされた命令は直接実行パイプラインには送られず、命令種別ごとに設けられたリザベーションステーションに格納される。

リザベーションステーションは、オペランドが揃って実行可能になった命令を順次実行パイプラインに送る。 また、リザベーションステーションは実行パイプラインの実行結果をモニタリングし、その実行結果をオペランドとして待つ命令があれば、実行結果をその命令のオペランドとして格納する。

逆依存と出力依存はレジスタリネームで解消し、フロー依存はリザベーションステーションで管理する。

レジスタバイパス

レジスタバイパス (register bypass) はある命令のオペランドがその前の命令の演算結果である場合に前の命令の演算結果をレジスタを経由せずに直接受け取ることにより、演算結果をレジスタに書くステージ (WB) とオペランドをレジスタから読むステージ (RR) を省略する、プロセッサの最適化手法の一つである。 これにより、前述のデータハザードの軽減が期待できる。

分岐予測

分岐予測 (branch prediction) は、プログラム実行の中で条件分岐命令が分岐するかしないかを予測する、プロセッサの最適化手法の一つである。

Out-of-Order実行と組み合わせて、予測に基づき条件分岐命令後の命令を先に実行してしまう方式を投機実行 (speculative execution) といい、これにより前述の制御ハザードの軽減が期待できる。

常に分岐が成立すると予測

例えば、for 文や while 文などのループの継続条件による条件分岐は最後のループを除いてすべて成立する。 このような理由から、常に分岐が成立すると予測したとしてもある程度の予測精度が期待できる。

飽和カウンタを用いる予測

飽和カウンタを用いた予測では、それぞれの条件分岐命令ごとに過去に分岐が成立したか (taken/not taken) の履歴を2ビットのカウンタ (飽和カウンタ) で記憶する。

飽和カウンタの値定義
00Strongly Not Taken
01Weakly Not Taken
10Weakly Taken
11Strongly Taken

メモリ管理

RAMメモリの種類

メモリの種類記憶素子面積 (容量当たり)価格 (容量当たり)備考
DRAM (Dynamic RAM)コンデンサ (キャパシタ)小さい安い揮発性があるため、一定間隔毎にリフレッシュ動作が必要。
SRAM (Static RAM)フリップフロップ大きい高い

キャッシュ

メモリアクセスには、今日のプロセッサのサイクル換算で約200サイクル近くのコストがかかる。 高コストなメモリアクセスを少しでも減らすため、メモリデータはより高速でよりプロセッサに近いSRAMにキャッシュされる。

フラグメンテーション

プログラムのメモリセグメントを互いに重ならないように (物理) メモリ空間に並べていく方式をセグメント方式という。

セグメント方式の問題として、プログラムが開始や終了を繰り返すとメモリ空間の空き領域の場所が散らばり、空き容量の合計に対して確保できるメモリ領域が少なくなるという問題が挙げられる。 この問題をフラグメンテーション (fragmentation, 英語で「断片化」という意味) という。

ページング方式

ページング方式 (paging) は、(物理) メモリ空間をページ (page) という一定サイズ (4kB or 8kB) の単位で管理する。

各ページには、実際の先頭メモリアドレス (以下、物理アドレス (physical address)) とは別に論理アドレス (logical address) が割り当てられる。 これにより、物理メモリ空間では散らばっている空き領域も、論理メモリ空間では連続する領域として使うことができる。

物理アドレスと論理アドレスの対応は、OSが管理するメインメモリ領域内のページテーブル (page table) というテーブルで管理される。

MMU

プロセッサに搭載されているメモリ管理ユニット (MMU, Memory Management Unit) は、論理アドレスからそのページの物理アドレスを調べ、実際のメモリアクセスを行う処理を担う。 また、MMUは内部にページテーブルのキャッシュをもっており、このキャッシュをTLB (Translation Lookaside Buffer) という。

つまり、MMUは物理メモリ空間にアクセスするための高速で透過的な手段を提供する。

ヒュージページ

今日ではメインメモリの容量が大きくなっているため、より大きなサイズ (数MB) をもつページが使えるようになっている。 これをヒュージページ (huge page) という。

Linuxには確保するメモリサイズに応じて自動的にヒュージページによるページングを行う、THP (Transparent Huge Pages) という機能がある。

しかし、CoW (Copy-on-Write) を前提としたプロセスフォークを行う一部のマルチプロセスアプリケーション (例: Redis) とは相性が悪い。

マルチプロセッサシステム

キャッシュコヒーレンシ制御

それぞれ独立したキャッシュをもつマルチプロセッサシステムにおいて、各プロセッサ間のキャッシュの整合性をとることをキャッシュコヒーレンシ制御という。

MSIプロトコル

MSIプロトコルは、キャッシュコヒーレンシ制御において最も基本的なプロトコルであり、キャッシュラインの状態を2つのフラグ (Invalid, Modified) で管理する。

InvalidModified状態
00Shared
01Modified
10Invalid
11存在しない

MSIはキャッシュラインがとりうる3つの状態 Modified, Shared, Invalid の頭文字である。

MSIプロトコルでは、各プロセッサはメモリの内容を書き換える前に他のプロセッサに対して同じメモリアドレスのキャッシュをインバリデートするよう要求を送る。 この要求をSnoop (英語で「覗き」という意味) とも呼ぶ。

また、キャッシュがライトバックキャッシュである場合は、メモリからデータを読む前に、他のプロセッサに対して同じメモリアドレスのキャッシュをメモリに書き戻すよう要求を送る。

MESIプロトコル

MESIプロトコルでは、MSIプロトコルのキャッシュの状態を表すフラグ (Invalid, Modified) に新たに Exclusive が加わる。

MESIプロトコルの Exclusive フラグは「そのキャッシュのデータは変更されておらず、他のプロセッサにキャッシュされていない」状態を表す。 これにより、Exclusive なキャッシュは他のプロセッサにインバリデート要求を送ることなく変更でき、高速化が期待できる。

MOSIプロトコル

MOSIプロトコルでは、MSIプロトコルのキャッシュの状態を表すフラグ (Invalid, Modified) に新たに Owned が加わる。

MOSIプロトコルの Owned フラグは「そのキャッシュのデータは変更されている」状態を表す。

ライトバックキャッシュにおいて、プロセッサ1が Owned 状態のキャッシュをもち、プロセッサ2が同じメモリアドレスのキャッシュに書き込むとき、プロセッサ1はプロセッサ2に変更後のキャッシュデータを直接送る。 これにより、メモリに書き戻す回数が減り、高速化が期待できる。 また、このときプロセッサ1はキャッシュの状態を Shared に変更し、プロセッサ2はキャッシュの状態を Owned に変更する。 つまり、Owned 状態は、そのキャッシュが追い出されるときに、そのデータをメモリに書き戻す責任があるかどうかを表すフラグにもなる。