プログラマーのためのCPU入門
書籍ページ
メモ
第1章/第2章
CPUの性能
$ CPU 時間 = \frac{実行命令数}{プログラム} \times \frac{クロックサイクル数}{実行命令数} \times \frac{秒数}{クロックサイクル数}
命令流
命令を順番に並べたもの。CPUはシーケンシャルに逐次実行するというのが基本のキですわ。
命令の粒度が小さい理由
ハードウェアを 単純にして高速化と小型化を実現できるという利点
とあるが命令の粒度が小さいと高速化する理由があんまりわからん。
命令の密度
命令自体を高速にするのではなく時間内に実行される命令の数を増やす(≒密度を増やす)
クロック
パルス列。1パルス1クロック。一定の周期で動作する。CPUの命令実行の単位/周期の基準。
レイテンシ
クロックサイクルの数。4クロックサイクル必要なら4レイテンシみたいな。
ステージ
CPUの命令を分割したもの
例えば命令1つを命令フェッチ/命令デコード/命令実行の3ステップに分けるみたいな感じ。各命令ごとはそれぞれ独立しているがステップの命令内における順序関係は依存関係にある。
パイプライン化
逐次実行ではなく前の命令の完了を待たずに次の命令を並行に実行する
スーパースカラ化
ステージ内でもさらに処理を分割して並列に1度に処理できる量を増やす技。物理的にパイプラインの配線を増やすなどで対応。
スーパーパイプライン化
ステージをさらに分割して平行処理できるステージを増やす
スーパースカラ化+スーパーパイプライン化
スーパーサイヤ人のFusionみたいな感じ
この辺、ずっと応用情報試験みたいな内容だ
第3章
命令流を妨げるものについて
データ依存関係
先行の命令が書き込むレジスタの値を後続の命令で利用する状態。前の命令待ちが発生する
スーパーパイプライン化/スーパースカラ化の効果がほぼ出なくなる
どうするか?
データ依存関係の無い後続の命令を先に実行する(アウトオブオーダー実行)
実行順を無視したら最終的な結果がぐちゃぐちゃになるのでは?
命令実行のステージの後に、命令のコミットステージを設ける。ぐちゃぐちゃに実行した命令の結果を一時的に保存しておいて正しい順番に並べ直すステージ。一時保存場所にはリオーダーバッファというテーブルを用意して使う。
プログラマができることとしてそもそもレイテンシの少ない命令を使うというのもある(詰まっても早く処理が完了する)
除算が遅いとかは有名だがGCCとかコンパイラ側でその辺は最適化してくれてそうだしあんま意識しなくて良い気がするがどうか
第4章
分岐命令について。PCレジスタを変更する命令。データ依存関係よりもCPU性能を遥かに落とす。なぜ?
パイプライン処理などで先行的にフェッチした命令をキャンセルしないといけないから。PCはインクリメントされていくが分岐命令で任意のPCカウンタに書き換えられてしまう。命令フェッチステージからやり直し。
無条件分岐(while)/条件分岐(if)/コール命令・リターン命令(関数とか)
分岐予測
分岐命令を実行する前の命令フェッチ段階でそれが分岐命令であることがわかるとパイプラインで以降の命令を早く実行させたりできる。BTB/BTACなどのテーブルを使う。
予測が外れた場合どうするか
第5章
キャッシュメモリ(主記憶/DRAM)が分岐命令と同等にソフトウェア実行を遅くするとはどういうこと?
DRAMがGHz程度で動作するとはいえ、CPUとメモリの間は離れていてバスで繋がっているのでメモリにアクセス(命令のフェッチやデータのロード)で数10サイクルから100サイクル程度の時間がかかる。つまりCPUの命令が一桁サイクルで実行されてるのに比べて10倍以上遅いというわけ。
緩和策
DRAMの一部をCPUの近くにコピーしてキャッシュとする
容量性ミス: キャッシュが溢れて2回目のアクセスにも関わらずDRAMの方へまたアクセスしないといけなくなるやつ
キャッシュのサイズは最大でも今だと128kb程度らしい
L1の後ろにL2キャッシュを置くことで対処してる。意地でもDRAMにアクセスせんぞ!という強い意志
ちなみにL1は4サイクルくらいL2だと15サイクルくらいかかる。DRAMの1/8程度なので全然良い。
SRAMをバカデカくしたらDRAMにアクセスしに行かなくて済むので良いという話はないか?
単純に、キャッシュの容量を主記憶と同程度にすることで、容量性ミスを解消でき ないものでしょうか。結論としては、現在のテクノロジーでは困難です。面積や電 力コストの観点もありますが、キャッシュの物理的な構成要素である SRAM(Static RAM)の速度の壁があります。
例として、容量が 32 キロバイトの SRAM について考えてみましょう。この SRAM には 32 キロ個、つまり約 3 万個の記憶領域があります。したがって、この SRAM 内 の 1 つの要素にアクセスすることは、約 3 万個の自由度から 1 つの要素を選択するこ とを意味します(図 5.6)。この選択を基本的な 2 分木(バイナリツリー)を用いて実 行しようとすると、log2 32000 = 15 回の選択が必要となる計算です。この 15 回の選 択に相当する操作を 1 サイクルで実行する†2 ためには、GHz 級の CPU だと、わずか数 100ps(ピコ秒)以内で動作できなければなりません。現在の半導体製造技術では、 この速度上の限界が 15 回強程度の選択になっています。そのため、100 キロバイト を大きく超える規模での大容量化は困難という状況です
SRAMの構造をもう少し深掘り
セットアソシアティブ方式
こんなの基本情報とかでやったっけか?
連想度/way数
第6章
仮想記憶/アドレス変換の際に発生する問題
仮想アドレス<------ページテーブル------->物理アドレス
ページテーブル: アドレスの1対1対応付けしただけのテーブル。プロセスごとに存在する。
ページテーブルはどこに管理されてる?
主記憶。つまりメモリ上にメモリ管理する情報を配置してる。
ページテーブルウォーク(主記憶上のページテーブルからアドレス変換のルールを取得するステップ)
CPU->主記憶(ページテーブルへアクセス)->取得したルールからアドレス変換->主記憶(変換した物理アドレスへアクセス)みたいな主記憶へのアクセスが1命令で2回発生しちゃうことがあるのでめちゃくちゃ遅くなる
TLB: ページテーブルのキャッシュみたいな感じのハードウェア
これについて調べてたら面白いページを見つけた
第7章
CPUから外部へのIO
外部IO: ディスプレイ/キーボード/ネットワーク/HDD/タイマーなど
メモリマップドIOしか知らなかったがIO用のアドレス空間を設けてそこに直接命令を出せる方法があるらしい
外部IOなぜ遅い?
コストと消費電力の問題で動作周波数を抑えるように作られている
経由するバスの都合
L1/L2のようなキャッシュが使えない
割り込み
DMAコントローラ
第9章
マルチプロセッサ。命令流自体を増やすことで全体として命令流の密度を上げる。
performance hybrid architecture / big.LITTLE
MIMD/SIMD
MIMD: 個別の命令流/データ流を処理する
SIMD: 同一の命令流/データ流を処理する
GPUとか
マルチプロセッサ間でメモリを共有するか分離するか、一部は共有で一部は分離にするかなど
マルチプロセッサはマルチプロセッサを想定したソフトウェア開発をしないと恩恵が受けられない
まだコンパイラとかが自動で良い感じにやってくれるようになってないんだ
並列/並行
キャッシュコヒーレンス
メモリ順序づけ
不可分操作