今回も引き続きMicroBlazeネタです.
Dhrystoneと呼ばれるベンチマークソフトウェアを動かしてみました.
ベンチマークということなのでMicroBlazeのキャッシュの容量を変化させて
どの程度の高速化ができるのか試してみたいと思います.
今回もVivado 2020.1とVitis 2020.1を使用します.
動かす準備
今回は前回, 前々回のプロジェクトを引き続き使用するのですが,
現状では, ハードウェア側でキャッシュが有効になっていません.
まずはキャッシュを有効にしてからDhrystoneを動かします.
FPGA側のプロジェクト
Vivado 2020.1でプロジェクトを開きます.
左のFlow NavigatorからOpen Block Designをクリックして
ダイアグラムを開きます.
MicroBlazeが中央におそらくあるとおもうのでダブルクリックで設定画面を開きます.
Use Instruction and Data Cachesにチェックを入れることで
キャッシュが有効になります.
キャッシュの詳細設定はNextを2回押して, 3ページ目にします.
とりあえずはどちらも8kBに設定しOKをクリックして設定を終えます.
ダイアグラムに戻ると上部にRun Connection Automatinが出てくるので
M_AXI_DCとM_AXI_ICにチェックを入れてOKを押します.
自動でAXI Interconnectに接続されるのでダイアグラムの作業は終了です.
保存してGenerate Bitstreamをクリックしてビットファイルを生成します.
生成が完了したらメニューバーからFile->Export->Export Hardwareで
xsaファイルを作成します.
ソフトウェア側のプログラム
Vitisでは以前のワークスペースと同じところで作業してもいいのですが
ごちゃごちゃするので新しくワークスペースを生成します.
今回はprjフォルダ以下vitis_dsとします.
左上からApplication Projectをクリックしてxsaファイルはprjフォルダ以下の
top_wrapper.xsaを指定します.
プロジェクト名は無難にDhrystone, テンプレートもDhrystoneを指定します.
テンプレートのDhrystoneは以下の2点でオリジナルと違うと記述されています.
- メモリサイズの問題でmallocを使用せず静的に確保している
- ベンチマークにかかった実際の時間やDMIPSと呼ばれるDhrystoneの指標を
出力できない
ということで前者は仕方ないのですが, 後者に至ってはベンチマークとしては
悲しい状態なので解決します.
幸いにもAXI Timerと呼ばれるカウンタがハードウェアに
追加してあるので利用します.
dhry.hは以下のHZの定義だけ変更します.
- #define HZ 100 + #define HZ (100 * 1000 * 1000)
dhry_1.cについては変更点が色々あるのでsourceフォルダ内に
変更後のファイルを置きました. 適時置き換えてください.
これで一通り完成です!
結果はシリアル出力されるのでシリアル変換モジュールをつないであげます.
実行するためにプロジェクトをビルドして, Debug Configurationsから
Single Application Debugを追加して実行します.
実行後すぐにResumeをクリックし, ベンチマークを走らせます.
(AXI Timerにはクロック100MHzを入力しているので約42秒でタイマーがオーバーフロー
して時間がおかしくなる可能性があるのですぐResumeしてください)
そうすると実行結果とどのくらい時間がかかったのかが出てきます.
Timer OK Dhrystone Benchmark, Version 2.1 (Language: C) Program compiled without 'register' attribute Number_Of_Runs set to 1000 Execution starts, 1000 runs through Dhrystone Execution ends Final values of the variables used in the benchmark: Int_Glob: 5 should be: 5 Bool_Glob: 1 should be: 1 Ch_1_Glob: A should be: A Ch_2_Glob: B should be: B Arr_1_Glob[8]: 7 should be: 7 Arr_2_Glob[8][7]: 1010 should be: Number_Of_Runs + 10 Ptr_Glob-> Ptr_Comp: -2147447452 should be: (implementation-dependent) Discr: 0 should be: 0 Enum_Comp: 2 should be: 2 Int_Comp: 17 should be: 17 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRING Next_Ptr_Glob-> Ptr_Comp: -2147447452 should be: (implementation-dependent), same as above Discr: 0 should be: 0 Enum_Comp: 1 should be: 1 Int_Comp: 18 should be: 18 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRING Int_1_Loc: 5 should be: 5 Int_2_Loc: 13 should be: 13 Int_3_Loc: 7 should be: 7 Enum_Loc: 1 should be: 1 Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING should be: DHRYSTONE PROGRAM, 1'ST STRING Str_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING should be: DHRYSTONE PROGRAM, 2'ND STRING User_Time: 3412838 Microseconds for one run through Dhrystone: 34.12 Dhrystones per Second: 29301.12
この結果はキャッシュを8kBにしたときなので容量を変化させると
どうなるか試してみたいと思います.
キャッシュ容量の変更
Vivadoに戻りMicroBlazeの設定3ページ目の8kBを32kBにします.
セーブして同様にGenerate Bitstreamでビットファイルを生成します.
生成が完了したらメニューバーからFile->Export->Export Hardwareで
xsaファイルを作成します.
Vitisでは新しいxsaファイルを反映させるため, Assistant内の
プラットフォームtop_wrapperを右クリックして
Update Hardware Specificationをクリック.
先程生成したxsaファイル(基本的にはそのままでOK)を指定してOKで反映させます.
反映されたあとはまた右クリックでBuildします.
その後アプリケーションのdhrystoneをビルドしてあげれば完了です.
(このUpdate Hardware Specificationを行うことで主にビットファイルが更新されます.
しかしハードウェア情報を司るxparameters.hというヘッダーファイルは
なぜか更新されません. Xilinxが意図しているのかどうかはわかりませんが…
ここでキャッシュを無効にした状態を確認したいとしてVivado内でキャッシュを無効にしても
xparameters.hには反映されずそのまま進めるとMicroBlazeが動いてくれませんでした.
この場合, Platformプロジェクトを作り直すことが手っ取り早いです.
既にあるIPの情報は更新されないのか, 何をしても更新されないのかは未検証ですが,
そういった事があるので気をつけないといけません.)
ベンチマーク結果
注意点は以下のとおりです.
- 基本的に実行時のメモリはDRAM上に載せた状態, キャッシュのみBRAM
- enable_cachesを初期化時に呼び出すことでキャッシュが有効化される
キャッシュの容量を変化させた結果を下の表に示します.
容量 | enable_caches |
1Dhrystone[us] |
DMIPS Higher is better |
備考 |
なし | 無効 | 15.8 | 63409.2 | Vivadoでキャッシュを無効化 実行時のメモリをBRAMに載せた状態 |
8kB | 有効 | 15.8 | 63409.2 | 実行時のメモリをBRAMに載せた状態 |
8kB | 有効 | 34.1 | 29301.1 | |
8kB | 無効 | 588.3 | 1699.8 | |
32kB | 有効 | 25.4 | 39348.3 | |
32kB | 無効 | 588.3 | 1699.8 | |
64kB | 有効 | 22.1 | 45271.3 | |
64kB | 無効 | 572.6 | 1746.4 |
結果から以下のことがわかりました.
- 実行時のメモリをDRAM上に載せただけの状態では少なくとも十数倍の時間がかかる
- キャッシュの容量が多いほどパフォーマンスは向上している
- キャッシュの有無に関わらず実行時のメモリをBRAMに載せたときが一番速い
BRAMに余裕がある場合はすべて載せてしまうのが確実です.
しかしなかにはそういうわけにはいかない状況もあるとは思うので, 許す限りのBRAMを
キャッシュに割り当てつつ実行時のメモリをDRAMへ逃がすという運用が最適解でしょうか.
まとめ
MicroBlaze上でベンチマークソフトであるDhrystoneを動作させてみました.
テンプレートでは時間測定ができなかったため, 別途計測する機構を追加し対応しました.
ベンチマーク結果よりキャッシュは多いほうがパフォーマンスが上がることが確認できました.
コメント