はじめに
別記事 「はじめに」 を参照してください。
この記事では「Argsort IP」 で紹介した ArgSort_AXI IP を Ultra96 に実装した結果を紹介します。
この記事で説明する ArgSort-Ultra96 はGitHub にて公開しています。
ArgSort-Ultra96 のデザイン
デザインブロック
ArgSort-Ultra96 は次図のようなデザインになっています。
Fig.1 ArgSort-Ultra96 のデザインブロック
ArgSort_AXI のバージョンは 1.2 です。前回説明した「ArgSort IP」で説明した IP のバージョンは 1.3 ですが、ArgSort-Ultra96 を実装した時期は少し古いため 1.2 を使っています。
ArgSort_AXI の STM_AXI は ZynqMP-ACP-Adapter を通して PS 部の S_AXI_ACP_FPD に接続しています。ZynqMP-ACP-Adapter と ACP に関する詳細な説明は次の記事を参照してください。
ArgSort_AXI、 ZynqMP-ACP-Adapter、AXI Interconnect のクロックは PS 部の PL_CLK0 を直接接続しています。PL_CLK0 の周波数はソフトウェアによって 250MHz に設定されます。
ArgSort_AXI のパラメータの設定値
ArgSort_AXI の主なパラメーターは次のように設定しています。これらのパラメーターのうち、MRG_WAYS、MRG_WORDS、STM_FEEDBACK の値を振ってそれ毎にビルドしたリソース量と実行時間を計測しました。
Table.1 ArgSort_AXI の主なパラメータの設定値
Parameter | Value | |
Categoly | Name | |
CORE | WORD_BITS | 32 |
INDEX_BITS | 32 | |
COMP_SIGN | FALSE | |
SORT_ORDER | 0 | |
MRG_WAYS | [16,32] (可変) | |
MRG_WORDS | [1,2](可変) | |
STM_FEEDBACK | [0,1,2] (可変) | |
STM_AXI | STM_AXI_ADDR_WIDTH | 32 |
STM_AXI_DATA_WIDTH | 128 | |
MRG_AXI | MRG_AXI_ADDR_WIDTH | 32 |
MRG_AXI_DATA_WIDTH | 128 |
結果
使用リソース
次表に MRG_WAYS、MRG_WORDS、STM_FEEDBACK を振ったそれぞれのデザインを Ultra96 に実装した時のリソースの使用状況を示します。なお、MRG_WASY が32 で MRG_WORDS が2 以上は Ultra96 で使われているデバイスには入りきりませんでした。
Table.2 Utilization
Design | Resources | Freq | ||||||
Name | MRG WAYS |
MRG WORDS |
STM FB |
CLB LUTs |
CLB Register |
BLOCK RAM |
DSPs | Freq [MHz] |
argsort_16_1_0 | 16 | 1 | 0 | 42142 | 27011 | 38 | 0 | 250 |
argsort_16_1_1 | 16 | 1 | 1 | 41865 | 27249 | 38 | 0 | 250 |
argsort_16_1_2 | 16 | 1 | 2 | 41799 | 26261 | 54 | 0 | 250 |
argsort_16_2_0 | 16 | 2 | 0 | 59246 | 55456 | 38 | 0 | 250 |
argsort_16_2_1 | 16 | 2 | 1 | 60828 | 57063 | 38 | 0 | 250 |
argsort_16_2_2 | 16 | 2 | 2 | 58819 | 55210 | 70 | 0 | 250 |
argsort_32_1_0 | 32 | 1 | 0 | 64126 | 45025 | 70 | 15 | 250 |
argsort_32_1_1 | 32 | 1 | 1 | 66621 | 46356 | 70 | 15 | 250 |
argsort_32_1_2 | 32 | 1 | 2 | 64988 | 44866 | 198 | 15 | 250 |
argsort_32_2_0 | 32 | 2 | 0 | resource over | ||||
zcu3egsbva48-1 resouce available | 70560 | 141120 | 216 | 360 |
Ultra96 で使われているデバイスが持っている LUT の数のうち、使用した LUT の数を次図に示します。
Fig.2 Utlization(LUTs %)
性能
次表にMRG_WAYS、MRG_WORDS、STM_FEEDBACK を振ったそれぞれのデザインを Ultra96 で実行した時にかかった時間とスループットを示します。
ソートするワード数は、5,000ワードから 1,000,000ワードまでを 5000 ワード毎にかかった時間を計測していますが、そのうち下の表には 10,000ワード、100,000ワード、1,000,000 ワードの時の時間を示しています。スループットは、5,000ワードから 1,000,000ワードまでを 5000 ワード毎に計測したスループット(ソートするワード数/かかった時間)の平均値を示しています。
参考までに最下行に ZynqMP の CPU(arm64) で numpy ライブラリの argsort() でソートした時間とスループットを示しています。
Table.3 Performance
Design | Sort time [msec] | Throughput Average [Mwords/sec] |
|||||
Name | MRG WAYS |
MRG WORDS |
STM FB |
10K [words] |
100K [words] |
1M [words] |
|
argsort_16_1_0 | 16 | 1 | 0 | 0.569 | 4.766 | 54.456 | 18.75 |
argsort_16_1_1 | 16 | 1 | 1 | 0.400 | 3.000 | 34.355 | 29.51 |
argsort_16_1_2 | 16 | 1 | 2 | 0.384 | 2.674 | 27.644 | 36.04 |
argsort_16_2_0 | 16 | 2 | 0 | 0.436 | 3.219 | 42.970 | 24.13 |
argsort_16_2_1 | 16 | 2 | 1 | 0.325 | 2.047 | 31.311 | 33.89 |
argsort_16_2_2 | 16 | 2 | 2 | 0.328 | 1.802 | 26.314 | 40.01 |
argsort_32_1_0 | 32 | 1 | 0 | 0.422 | 3.384 | 39.381 | 25.69 |
argsort_32_1_1 | 32 | 1 | 1 | 0.341 | 2.494 | 27.748 | 36.31 |
argsort_32_1_2 | 32 | 1 | 2 | 0.595 | 2.711 | 27.433 | 36.79 |
ZynqMP(arm64) numpy.argsort() | 1.790 | 32.036 | 1320.921 | 1.49 |
次図にスループットの平均値をグラフで示します。
Fig.3 Throughput Average [Mwords/sec]
テストの手順
テスト環境
- ハードウェア: Avnet Ultra96-V2
- ソフトウェア: ZynqMP-FPGA-Linux v2021.1.1 (Linux Kernel 5.10 + Debian 11)
インストール
Ultra96/Ultra96-V2 の準備
Ultra96/Ultra96-V2 に ZynqMP-FPGA-Linux または ZynqMP-FPGA-Ubuntu20.04 をインストールします。インストール方法は次のURLを参照してください。
- https://github.com/ikwzm/ZynqMP-FPGA-Linux/blob/v2021.1.1/doc/install/ultra96v2.md
- https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04/blob/v2021.1-desktop-1/doc/install/ultra96v2-desktop.md
- 『UltraZed/Ultra96/Ultra96-V2/KV260 向け Debian GNU/Linux (v2021.1版) ブートイメージの提供』@Qiita
ArgSort-Ultra96 のダウンロード
次のように Ultra96/Ultra96-V2 に ArgSort-Ultra96 をダウンロードします。
fpga@debian-fpga:~/$ git clone --branch 1.2.1 git://github.com/ikwzm/ArgSort-Ultra96.git
fpga@debian-fpga:~/$ cd ArgSort-Ultra96
FPGA ビットストリームとデバイスツリーのインストール
次のようにテストの対象となるデザインのビットストリームファイルとデバイスツリーを Ultra96/Ultra96-V2 にインストールします。デバイスツリーのインストールには Device Tree Overlay を使用しています。インストールするための Rakefile を用意しているので、rake コマンドを実行してインストールします。環境変数 TARGET にはデザイン名を指定します。
fpga@debian-fpga:~/ArgSort-Ultra96$ sudo TARGET=argsort_16_2_2 rake install
gzip -d -f -c argsort_16_2_2.bin.gz > /lib/firmware/argsort_16_2_2.bin
./dtbocfg.rb --install argsort --dts argsort_16_2_2_5.4.dts
/tmp/dtovly20201118-1281-1tf8e0q: Warning (unit_address_vs_reg): /fragment@2/__overlay__/uio_argsort: node has a reg or ranges property, but no unit name
/tmp/dtovly20201118-1281-1tf8e0q: Warning (avoid_unnecessary_addr_size): /fragment@2: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property
[10952.701089] fpga_manager fpga0: writing argsort_16_2_2.bin to Xilinx ZynqMP FPGA Manager
[10952.861395] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /fpga-full/firmware-name
[10952.874409] fclkcfg amba_pl@0:fclk0: driver version : 1.7.1
[10952.879998] fclkcfg amba_pl@0:fclk0: device name : amba_pl@0:fclk0
[10952.886447] fclkcfg amba_pl@0:fclk0: clock name : pl0_ref
[10952.892194] fclkcfg amba_pl@0:fclk0: clock rate : 249999998
[10952.898138] fclkcfg amba_pl@0:fclk0: clock enabled : 1
[10952.903363] fclkcfg amba_pl@0:fclk0: remove rate : 1000000
[10952.909107] fclkcfg amba_pl@0:fclk0: remove enable : 0
[10952.914327] fclkcfg amba_pl@0:fclk0: driver installed.
[10952.935858] u-dma-buf udmabuf-argsort-in: driver version = 3.2.0
[10952.941868] u-dma-buf udmabuf-argsort-in: major number = 241
[10952.947704] u-dma-buf udmabuf-argsort-in: minor number = 0
[10952.953360] u-dma-buf udmabuf-argsort-in: phys address = 0x0000000070400000
[10952.960498] u-dma-buf udmabuf-argsort-in: buffer size = 33554432
[10952.966762] u-dma-buf amba_pl@0:udmabuf_argsort_in: driver installed.
[10952.988678] u-dma-buf udmabuf-argsort-out: driver version = 3.2.0
[10952.994773] u-dma-buf udmabuf-argsort-out: major number = 241
[10953.000697] u-dma-buf udmabuf-argsort-out: minor number = 1
[10953.006438] u-dma-buf udmabuf-argsort-out: phys address = 0x0000000072400000
[10953.013662] u-dma-buf udmabuf-argsort-out: buffer size = 33554432
[10953.020014] u-dma-buf amba_pl@0:udmabuf_argsort_out: driver installed.
[10953.085033] u-dma-buf udmabuf-argsort-tmp: driver version = 3.2.0
[10953.091130] u-dma-buf udmabuf-argsort-tmp: major number = 241
[10953.097060] u-dma-buf udmabuf-argsort-tmp: minor number = 2
[10953.102804] u-dma-buf udmabuf-argsort-tmp: phys address = 0x0000000074400000
[10953.110028] u-dma-buf udmabuf-argsort-tmp: buffer size = 134217728
[10953.116466] u-dma-buf amba_pl@0:udmabuf_argsort_tmp: driver installed.
テストの実行
サンプルデータの生成
ソートするデータのサンプルを用意します。サンプルデータを生成する Python スクリプト generage_sample.py を用意しています。生成するデータの大きさを指定してサンプルデータを生成します。このスクリプトを直接実行するか、rake コマンドから実行します。
fpga@debian-fpga:~/ArgSort-Ultra96$ rake sample_0001000000.npy
python3 generate_sample.py --size 1000000 --sample sample_0001000000.npy
generate_sample: sample_file : sample_0001000000.npy
generate_sample: size : 1000000
generate_sample: time : 44.262 [msec]
期待値データの生成
サンプルデータを Python の numpy.argsort() を使ってソートしたデータを用意します。これは ArgSort-Ultra96 によってソートした結果データと比較して正常にソートされたかをチェックするのに使います。期待値データを生成する Python のスクリプト generate_expect.py を用意しています。このスクリプトを直接実行するか、rake コマンドから実行します。ついでに期待値データを生成する時間を計測してログに残しておきます。
fpga@debian-fpga:~/ArgSort-Ultra96$ rake expect_0001000000.npy
python3 generate_expect.py --sample sample_0001000000.npy --expect expect_0001000000.npy --log expect.log
generate_expect: sample_file : sample_0001000000.npy
generate_expect: expect_file : expect_0001000000.npy
generate_expect: size : 1000000
generate_expect: average_time : 1325.425 # [msec]
generate_expect: throughput : 0.754 # [mwords/sec]
ArgSort-Ultra96 を実行
ArgSort-Ultra96 を実行してサンプルデータをソートします。ソートされた結果のデータを保存し、ソートにかかった時間を計測してログに残します。ArgSort-Ultra96 を実行する Python スクリプト argsort_test.py を用意しています。また、ArgSort-Ultra96 がソートした結果と numpy.argsort() がソートして期待値とを比較します。比較する Python スクリプト check_result.py を用意しています。これらのスクリプトを直接実行するか、rake コマンドから実行します。
fpga@debian-fpga:~/ArgSort-Ultra96$ rake test_1000000
python3 argsort_test.py --sample sample_0001000000.npy --result result_0001000000.npy -n 10 -d 2 --log argsort_16_2_2.log
argsort_test : Version : 1.2
argsort_test : Ways : 16
argsort_test : Words : 2
argsort_test : Feedback : 2
argsort_test : WordBits : 32
argsort_test : IndexBits : 32
argsort_test : Sort Order : 0
argsort_test : Sign Compare : 0
argsort_test : Max Size : 268435455
argsort_test : Debug Enable : 1
argsort_test : sample_file : sample_0001000000.npy
argsort_test : size : 1000000
argsort_test : debug_mode : 2
argsort_test : loops : 10
argsort_test : time : 26.149 # [msec]
argsort_test : time : 26.515 # [msec]
argsort_test : time : 26.186 # [msec]
argsort_test : time : 26.037 # [msec]
argsort_test : time : 26.611 # [msec]
argsort_test : time : 26.458 # [msec]
argsort_test : time : 25.907 # [msec]
argsort_test : time : 26.645 # [msec]
argsort_test : time : 26.656 # [msec]
argsort_test : time : 25.674 # [msec]
argsort_test : result_file : result_0001000000.npy
argsort_test : average_time : 26.284 # [msec]
argsort_test : throughput : 38.046 # [mwords/sec]
argsort_test : Debug_Time(0): 25.199 # [msec]
argsort_test : Debug_Time(1): 16.501 # [msec]
argsort_test : Debug_Time(2): 4.860 # [msec]
argsort_test : Debug_Time(3): 3.838 # [msec]
python3 check_result.py --sample sample_0001000000.npy --result result_0001000000.npy --expect expect_0001000000.npy
check_result: sample file : sample_0001000000.npy
check_result: expect file : expect_0001000000.npy
check_result: result file : result_0001000000.npy
check_result: OK
アンインストール
デバイスツリーのアンインストール
テストが終わったらデバイスツリーをアンインストールします。別のデザインをインストールして実行するためには必ず現在のデザインをアンインストールしておく必要があります。アンインストールにもインストールと同様に Device Tree Overlay を使います。インストールと同様に rake コマンドを使ってアンインストールします。
fpga@debian-fpga:~/ArgSort-Ultra96$ sudo rake uninstall
./dtbocfg.rb --remove argsort
[11218.745653] u-dma-buf amba_pl@0:udmabuf_argsort_tmp: driver removed.
[11218.757907] u-dma-buf amba_pl@0:udmabuf_argsort_out: driver removed.
[11218.770021] u-dma-buf amba_pl@0:udmabuf_argsort_in: driver removed.
[11218.777459] fclkcfg amba_pl@0:fclk0: driver removed.
デザインのビルド
ビルド環境
- 開発ツール: Xilinx Vivado 2020.1 or 2020.2
- IP: ArgSort_AXI IP 1.2、ZynqMP-ACP-Adapter IP v0.4
ArgSort-Ultra96 のダウンロード
次のようにビルド用コンピューターに ArgSort-Ultra96 をダウンロードします。
shell$ git clone --branch 1.2.1 --recursive git://github.com/ikwzm/ArgSort-Ultra96.git
shell$ cd ArgSort-Ultra96
ビルド用スクリプトファイル
各デザイン毎にスクリプトファイルを用意しています。 argsort_16_2_2 を例にすると次のようになります。
- argsort_16_2_2/
- create_project.tcl
- design_1.bif
- design_1_bd_2020.1.tcl
- design_1_bd_2020.2.tcl
- design_1_pin.xdc
- implementation.tcl
ビルド環境の設定
Xilinx Vivado 2020.1 または 2020.2 が動作する環境を設定します。
shell$ source /opt/Xilinx/Vivado/2020.2/settings64.sh
プロジェクトの生成
プロジェクトを生成するためには、スクリプトが格納されているディレクトリに移動して vivado で create_project.tcl を実行します。以下の例では vivado のコマンドラインから実行しています。
shell$ cd argsort_16_2_2
shell$ vivado -mode batch -source create_project.tcl
論理合成と配置配線
プロジェクトの論理合成と配置配線をしてビットストリームファイルを生成するためには implementation.tcl を使用します。
shell$ vivado -mode batch -source implementation.tcl
生成されたビットストリームファイルは project.runs/impl_1/design_1_wrapper.bit です。なお、このスクリプトでビットストリームファイルを生成した場合は、使用リソースやタイミングチェックなどのレポートファイル project.rpt が生成されます。
バイナリ—ファイルの生成
ビットストリームファイルから PL はダウンロードするためのバイナリ—ファイルを生成するためには、bootgen コマンドと design_1.bif を使います。
shell$ bootgen -image design_1.bif -arch zynqmp -w -o ../argsort_16_2_2.bin
shell$ cd ..
shell$ gzip argsort_16_2_2.bin
所感
バス帯域について
ArgSort で使用しているマージソーターコアは「マルチワード マージソート ノード」で説明したように1クロックあたりに出力できるワード数を複数ワードにすることができます。ArgSort_AXI IP 1.2 ではこのパラメータの値は MRG_WORDS で指定します。
本来ならこのパラメータを1から2に変更することで性能が倍になるはずです。しかし次の表で示すようにそれほどの差は無いように思われます。
Table.4 MRG_WORDSの違いによる性能の比較
Design | Throughput Average [Mwords/sec] |
MRG_WORDS 1-> 2 Up [%] |
|||
Name | MRG WAYS |
MRG WORDS |
STM FB |
||
argsort_16_1_0 | 16 | 1 | 0 | 18.75 | 28.69 % Up |
argsort_16_2_0 | 2 | 24.13 | |||
argsort_16_1_1 | 16 | 1 | 1 | 29.51 | 14.84 % Up |
argsort_16_2_1 | 2 | 33.89 | |||
argsort_16_1_2 | 16 | 1 | 2 | 36.04 | 11.02 % Up |
argsort_16_2_2 | 2 | 40.01 |
そこで ArgSort IP の MRG-AXI の波形を ILA(Integrated Logic Analyzer) で実測してみました。
Fig.4 ArgSort IP の MRG-AXI の波形
この波形をみて分かる通り、データの読み出しと書き込みが同時に発生すると、読み出しと書き込み双方の転送速度が落ちているのがわかります。
これは考えてみれば当たり前の話で、もし argsort_16_2_2 がフルに動作するためには MRG-AXI のデータ帯域は 128bit(16Byte=ソートデータの2ワード分)×250MHz(動作周波数)×2(読み出しと書き込みの同時アクセス) で8GByte/sec 必要になります。しかし、Ultra96-V2 のシステムメモリである DDR-SDRAM は32bit(4Byte)×2(DDR分)×533MHz で 4.264GByte/sec しかありません。つまり元々システムメモリの帯域が足りなかったのです。私の設計ミスでした。
参照
- 目次: 「はじめに」
- 次回: 「ArgSort-Kv260」
- 前回: 「ArgSort IP」
- https://github.com/ikwzm/ArgSort-Ultra96
- https://github.com/ikwzm/Merge_Sorter
- https://github.com/ikwzm/ZynqMP-FPGA-Linux
- https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04
- 『ZynqMP ACP と AXI をつなぐアダプタ』 @Qiita
- 『UltraZed/Ultra96/Ultra96-V2/KV260 向け Debian GNU/Linux (v2021.1版) ブートイメージの提供』@Qiita