自作RISC-V CPUコアの方は、いくつかのコンフィグレーションにおいてDhrystoneを完走させることができるくらいになってきた。 RASの実装を変更してからCALL/RETでの分岐予測ミスが減ったので多少性能が上がったと思うのだが、久しぶりにDhrystoneを測定してみる。
前回の構成でシミュレーションを行ったのがこちら。
Configuration | IPC |
---|---|
tiny | 0.56 |
small | 0.84 |
standard | 0.92 |
big | 0.92 |
いくつか分岐予測器のバグを修正して少しだけ性能が改善した。
ただ相変わらず予想ほど性能が出ていない。5命令発行なんだからもう少し性能が出てほしいのだけれどもな。 というわけでどれだけの効率になっているのか調査してみる。
1000サイクル当たりの命令効率は、全体の1/3くらいの命令が死んでしまっており、この効率の悪さは残っている。
} " 132386" : { "commit" : { "cmt" : 615, "inst" : 1551, "dead" : 704, "reason" : { "exc" : 0, "branch" : 520, "previnst" : 0, "anotherflush" : 52, "ext_kill" : 132 }}, "icache" : { "request" : 758, "hit" : 758, "miss" : 0 }, "dcache" : { "port[0]" : { "req" : 0, "hit" : 0, "miss" : 0, "conflict" : 0 } "port[1]" : { "req" : 0, "hit" : 0, "miss" : 0, "conflict" : 0 } "port[2]" : { "req" : 0, "hit" : 0, "miss" : 0, "conflict" : 0 } "port[3]" : { "req" : 184, "hit" : 152, "miss" : 0, "conflict" : 32 } "port[4]" : { "req" : 273, "hit" : 257, "miss" : 0, "conflict" : 16 } "port[5]" : { "req" : 182, "hit" : 142, "miss" : 0, "conflict" : 40 } "port[6]" : { "req" : 64, "hit" : 28, "miss" : 0, "conflict" : 36 } }, "branch" : { "execute" : 367, "cmp" : { "execute" : 243, "hit" : 231 }, "uncond" : { "ret" : { "execute" : 64, "hit" : 60}, "others" : { "execute" : 60, "hit" : 60 }}, }, }
実際問題、1000サイクルの内実行に成功したのは1551命令で、704命令は死んでしまっている。 こう考えるとそもそも全部成功したとしても1000サイクルで2200命令しか実行できていないことになり、IPCはどんなに頑張っても2.2を超えないことになってしまう。この辺のボトルネックも解析が必要だ。
本当にこんなに命令が死んでいるのか?ということでカウンタの値を波形表示してみると以下のようになった。 なるほど着実に命令が死んでいる。ログを見る限り単純比較命令のヒット率は231/243で95%程度、ret命令のRAS更新ミスによる失敗も4/64でそんなに悪くない。やはり一回死ぬだけで影響が大きいということが言えそうな気がしている。
次に見るべきは、
- 分岐命令の効率をより向上させる方法 (これはTAGEなどの導入が挙げられる)
- そもそも命令実行効率を上げる方法 (このままでは分岐が100%ヒットしたとしてもIPC=2.2が頭打ちになってしまう)
- まずは命令の切り出し効率だろうか。5命令ディスパッチのスロットを、平均どれくらい使っているか、という話。
というものが挙げられるだろう。もう少し調査していこう。