|
|
|
発展課題
|
|
|
|
============
|
|
|
|
|
|
|
|
発展課題は好きなことをしていただいて構いませんが、以下にいくつか例をあげておきます。
|
|
|
|
|
|
|
|
### パイプライン化
|
|
|
|
|
|
|
|
* 難易度:2
|
|
|
|
|
|
|
|
プロセッサの性能を上げる最も簡単な方法はクロック周波数を上げることですが、回路の遅延があるため、無制限に上げることはできません。
|
|
|
|
パイプライン化を施すと、各パイプラインステージでの遅延を短くすることができるため、クロック周波数をさらに上げることが可能になります。
|
|
|
|
|
|
|
|
パイプラインレジスタを追加するのに加え、フォワーディング、ストールなどを考える必要があります。
|
|
|
|
|
|
|
|
教科書的な説明ではパイプラインの段数は5段が一般的ですが、最も高速化する段数を探してみるのも面白いかもしれません。クリティカルパス(レジスタからレジスタへの経路のうちで、最も長い遅延を生み出す経路)はどこになっているでしょうか?
|
|
|
|
|
|
|
|
### RV32Mへの対応
|
|
|
|
|
|
|
|
* 難易度:2
|
|
|
|
|
|
|
|
やや複雑な計算を行う命令を追加することでもプロセッサの性能を上げることができます。乗算はその典型例でしょう。
|
|
|
|
|
|
|
|
RISC-V では、最小構成なプロセッサを作れるようにするため、乗除算命令は拡張命令セット(M拡張)に含まれています。この拡張命令に対応していない場合、コンパイラは加算やシフトを駆使して乗算を実現するコードを生成しますが、当然命令数が増大します。
|
|
|
|
|
|
|
|
準備として、RV32IM に対応したコードを出力するコンパイラを作り直す必要があります。
|
|
|
|
|
|
|
|
これを実装するとクリティカルパスが長くなり、今まで動いていた動作周波数で正しく動作しなくなるかもしれません。これに対処するにはどうしたらよいでしょうか?
|
|
|
|
|
|
|
|
### 分岐予測器の実装
|
|
|
|
|
|
|
|
* 難易度:3
|
|
|
|
|
|
|
|
パイプライン化を完成させた後に行う課題になります。
|
|
|
|
|
|
|
|
パイプライン化を行うと、適宜ストールを発生させる必要があります。特に、ストールの要因として大きな部分を占めるのは、分岐命令です。分岐命令の結果が確定するまで、次の PC がわからないことが原因ですが、「多分次の PC はこの値」と予測できれば、投機的に次の命令を実行することができます(投機的に、というのは「無駄になるかもしれないが、予測が当たれば(性能面で)得になる」というようなニュアンスです)。
|
|
|
|
|
|
|
|
分岐予測ミス時に、間違って実行しかけてしまった命令をなかったことにする機構を実装する必要があります。
|
|
|
|
|
|
|
|
分岐予測器は凝りだすと果てがありませんが、ごく単純な「常に分岐しない(次の PC は PC+4)と予想」「前回と同じ場所に分岐すると予想」などでも十分でしょう。凝った分岐予測器にチャレンジしたいとしても、それにいきなり手を出すのは推奨できません。まずは簡単な分岐予測器を作り、分岐予測ミス時にも正しく動作するような機構を正しく実装できたことを確信してから、分岐予測器を取り換えるのがおすすめです。
|
|
|
|
|
|
|
|
ちなみに、分岐予測ミス時の回復を正しく実装してさえいれば、分岐予測器が間違った実装になっていたとしても、全体として正しく動いてしまいます。しかし、性能はあがりません。そのような、正しく動作するものの性能が思っているものと違うものになってしまう、というバグはパフォーマンスバグと呼ばれます。プログラムが正しく動いていることからだけではバグっているのかはわからないため、シミュレーター上で正しく動いているかを確認する必要があります。
|
|
|
|
|
|
|
|
### (インオーダーの)スーパースカラ化
|
|
|
|
|
|
|
|
* 難易度:5
|
|
|
|
|
|
|
|
CPU の実行すべき命令は、必ずしも直前の命令の結果を使うわけではないため、二つ以上の命令を同時に実行しても問題がない場合もあります。これを、**命令レベル並列性**と呼びます。命令レベル並列性をハードウェアで抽出し、性能を上げるのがスーパースカラプロセッサです。
|
|
|
|
|
|
|
|
二つの命令を同時に実行しても問題ないかを判断する論理回路を記述する必要があります。その他、いろいろな部分に、細かい変更が必要になります。一命令ずつ実行していた時では起こりえない状況も発生するため、注意深く考えることが重要です。
|
|
|
|
|
|
|
|
可能な限り並列実行できるようにするために考えるべきことはそれなりに多く、いきなりそれを全部考慮するのは大変です。
|
|
|
|
まずはごく単純な、間違いの起こりようのない例でだけ並列実行できるようにするのがコツです。その後、並列実行できるパターンを段階的に追加していけばよいでしょう。
|
|
|
|
|
|
|
|
### アウトオブオーダー実行できるようにする
|
|
|
|
|
|
|
|
* 難易度:5+
|
|
|
|
|
|
|
|
インオーダーのスーパースカラでは、既に実行可能な命令が後ろの方にあっても、前から順番に実行していかないといけないという制約の都合上、その命令を実行することができません。そのような場合、Exec Unit が遊んでいることになり、もったいないです。アウトオブオーダー実行できれば、そのような命令を先に実行することができ、遊んでいる Exec Unit が有効活用されるため、性能が向上します。
|
|
|
|
|
|
|
|
Exec Unit 以外はほとんど書き直しになってしまうので、実装量は多くなります。外から見た結果が、命令の順番通り(インオーダーに)実行した時と必ず一致する必要があるため、考えることがたくさんあります。 |