0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

VHDL で書くマージソーター(ArgSort-Ultra96)

Last updated at Posted at 2022-03-28

はじめに

別記事 「はじめに」 を参照してください。

この記事では「Argsort IP」 で紹介した ArgSort_AXI IP を Ultra96 に実装した結果を紹介します。

この記事で説明する ArgSort-Ultra96 はGitHub にて公開しています。

ArgSort-Ultra96 のデザイン

デザインブロック

ArgSort-Ultra96 は次図のようなデザインになっています。

Fig.1 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 %)

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]

Fig.3 Throughput Average [Mwords/sec]


テストの手順

テスト環境

インストール

Ultra96/Ultra96-V2 の準備

Ultra96/Ultra96-V2 に ZynqMP-FPGA-Linux または ZynqMP-FPGA-Ubuntu20.04 をインストールします。インストール方法は次のURLを参照してください。

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.

デザインのビルド

ビルド環境

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 の波形

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 しかありません。つまり元々システムメモリの帯域が足りなかったのです。私の設計ミスでした。

参照

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?