exStickGEとMicroBlazeでDhrystoneを動かしてみた

技術紹介

今回も引き続き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_DCM_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]
Lower is better

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を動作させてみました.
テンプレートでは時間測定ができなかったため, 別途計測する機構を追加し対応しました.
ベンチマーク結果よりキャッシュは多いほうがパフォーマンスが上がることが確認できました.

コメント

タイトルとURLをコピーしました