HPC アプリを FPGA 上で加速! (4) Ultra96-V2 での実行

前回までは Alveo U50 上で Vector Add の template や CG 法のプログラムを実行しましたが、今回はエンベデッドプラットフォームと呼ばれる ZCU102, ZC706, Ultra96-V2 などで CG 法のプログラムを実行してみます。

なお、このブログの第2回でも少し触れたのですが、Vitis 2020.2 では、実機の Hardware での実行と Emulation-SW でのエミュレーションの演算結果が異なることがあるようです。そのため、今回のブログでは主に 2020.1 での手順を説明し、2020.2 での手順を補足することにします。

プラットフォームのインストール

このブログで扱う FPGA カードとテストボード
図1: このブログで扱う FPGA カードとテストボード (第1回の再掲)

エンベデッドプラットフォームと呼ばれている ZCU102ZC706 および Ultra96-V2 では、図1に示すように FPGA と ARM の CPU が1チップの SoC として実装されています。ARM ではホストプログラムのみを動かすことも可能ですが、今回は PetaLinux と呼ばれる Linux の OS 上でホストプログラムを動かしてみます。このブログで使っている連立一次方程式を解く CG 法のプログラムでは、コマンドラインからオプションを指定したり、係数行列データをファイルから入力したりしますが、OS 上ならばソースファイルを修正せずにホストプログラムを動かすことができます。

以下、ZCU102, ZC706 のプラットフォームのダウンロード、Ultra96-V2 のプラットフォームのダウンロード、Ultra96-V2 の prebuilt vadd の実行の順に説明していきますが、お持ちのテストボードにあわせてご参照下さい。

ZCU102, ZC706 のプラットフォームのインストール

Xilinx の Vitis ソフトウェアプラットフォームのインストール のサイトなどにインストール方法が解説されていますが、以下のような手順で Xilinx のサイトからファイルをダウンロードしてインストールします。

  1. Vitis のインストール
  2. ザイリンクス ラインタイム (XRT; Xilinx Run Time) のインストール
  3. Vitis エンベデッドベースプラットフォーム (Embedded Base Platform) のインストール
    1. ZCU102: xilinx_zcu102_base_202010_1.zip
    2. ZC706: xilinx_zc706_base_202010_1.zip
  4. エンベデッド Vitis プラットフォーム向けの共通イメージ (Common Images for Embedded Vitis Platforms) のインストール
    1. ZCU102: xilinx-zynqmp-common-v2020.1.tar.gz
    2. ZC706: xilinx-zynq-common-v2020.1.tar.gz

手順3でダウンロードするエンベデッドベースプラットフォームのファイルのことを、このブログでは誤解のない限り単にプラットフォームまたはプラットフォームファイルなどと呼びます。

Xilinx のサイトからは多くのファイルをダウンロードできるようになっていますが、何をダウンロードすべきか迷うこともあるかと思いますので、このブログでは、何をダウンロードすべきかを中心に説明します。ダウンロードしたファイルのインストール作業自体は、やや時間がかかるものもありますが、それほど迷うことはないかと思います。また、ZCU102 と同様の手順で ZCU104 などのプラットフォームもダウンロードとインストールが可能です。

ダウンロードやインストールには Xilinx のサイトへサインインするためのアカウントが必要になる箇所があります。必要に応じて、メールアドレスとパスワードを登録して作業を進めて下さい。

また、上記の手順1-4のうち、手順2のみは root でインストールする必要がありますが、それ以外はユーザ権限でのインストールも可能なようです。

Vitis のインストール

Vitis のダウンロードサイト
図2: Vitis のダウンロードサイト

手順1の Vitis は図2に示すような Vitis のダウンロードサイト から Vitis コア開発キット 2020.1 としてダウンロードできます。インストーラー自体は短時間でダウンロードできますが、このインストーラーから Vitis をダウンロードしてインストールするには少々時間がかかります。

XRT のインストール

Vitis エンベデッドプラットフォームのサイト
図3: Vitis エンベデッドプラットフォームのサイト

Vitis のダウンロードサイトで、エンベデッドプラットフォームをクリックし、適切な Version (今回は 2020.1) をクリックすると、図3のような Vitis エンベデッドプラットフォームのダウンロードサイト になります。手順2-4のファイルがこのページがダウンロードできるのですが、まず手順2のザイリンクスランタイム (XRT) をダウンロード、インストールします。Ubuntu や RedHat などの Linux のディストリビューションやバージョンごとに適切なファイルをダウンロードすれば問題なくインストールできると思います。

エンベッドベースプラットフォームのインストール

Vitis エンベデッドベースプラットフォームのダウンロード
図4: Vitis エンベデッドベースプラットフォームのダウンロード

手順2の XRT と同じページを下へスクロールすると、図4のように手順3の ZCU102 や ZC706 のエンベデッドベースプラットフォームをダウンロードできるリンクが現れます。ZCU102 ベース 2020.1ZC706 ベース 2020.1 をクリックするとそれぞれ以下のファイルがダウンロードできます。

  • ZCU102: xilinx_zcu102_base_202010_1.zip
  • ZC706: xilinx_zc706_base_202010_1.zip

Vitis 2020.1 がデフォルトの /tools/Xilinx/Vitis/2020.1 にインストールされているなら、ダウンロードしたファイルを /tools/Xilinx/Vitis/2020.1/platforms ディレクトリの下に展開して、以下のようなディレクトリができていることを確認して下さい。

  • /tools/Xilinx/Vitis/2020.1/platforms/xilinx_zc706_base_202010_1
  • /tools/Xilinx/Vitis/2020.1/platforms/xilinx_zcu102_base_202010_1

共通イメージのインストール

手順2, 3のページをさらに下へスクロールすると、図5, 6のように手順4のZYNQMP の共通イメージと ZYNQ の共通イメージへのリンクが現れます。ZCU102 や ZCU104 なら ZynqMP の共通イメージ, ZC706 なら Zynq の共通イメージ をクリックして、対応するファイルをダウンロードします。

ZYNQMP の共通イメージのダウンロード
図5: ZYNQMP の共通イメージのダウンロード
ZYNQ の共通イメージのダウンロード
図6: ZYNQ の共通イメージのダウンロード

ダウンロードした共通イメージのファイルを展開するディレクトリは特に決まっていません。ここでは /opt/common_images/2020.1 の下に展開するものとします。

  • /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1
  • /opt/common_images/2020.1/xilinx-zynq-common-v2020.1

さらに、ダウンロードしたファイルに含まれるスクリプトを実行して SDK と呼ばれるものをインストールする必要があります。zynqmp の場合は以下のように sdk.sh というスクリプトを実行します。target directory を指定するように求められますが、今回は共通イメージのインストール先を指定することにします。

# cd /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1
# ./sdk.sh
(メッセージは省略します)
Enter target directory for SDK (default: /opt/petalinux/2020.1): /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1

少し時間がかかりますが、コマンド実行後は以下のようなディレクトリやファイルが作成されていることを確認して下さい。後述のセクションでも説明しますが、これらは Vitis でのプログラムの build で必要になります。

  • /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/sysroots/aarch64-xilinx-linux
  • /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/rootfs.ext4
  • /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/Image

ZC706 用の Zynq の共通イメージについても同様に sdk.sh スクリプトを実行すれば以下のようなディレクトリやファイルが生成されます。

  • /opt/common_images/2020.1/xilinx-zynq-common-v2020.1/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi
  • /opt/common_images/2020.1/xilinx-zynq-common-v2020.1/rootfs.ext4
  • /opt/common_images/2020.1/xilinx-zynq-common-v2020.1/uImage

ファイル名などから推測できるかもしれませんが、共通イメージとしてインストールしたのは、ARM CPU でブートする Linux のファイルシステムになります。

ZCU102 や ZC706 のプラットフォームのダウンロードとインストールは以上のようになります。ZCU104 の場合や Vitis 2020.2 の場合も、適宜、ディレクトリ名やファイル名を読み替えれば同様にダウンロードやインストールが可能です。

次のセクションではUltra96-V2 のプラットフォームのダウンロードやインストール方法を説明しますので、ZCU102 などでアプリケーションを build する場合は次のセクションを飛ばして読み進めてもらえればと思います。

Ultra96-V2 のプラットフォームのインストール

Ultra96V2 の場合、ZCU102 や ZC706 と違って、エンベデッド Vitis プラットフォーム向けの共通イメージ (Common Images for Embedded Vitis Platforms) のインストールは不要ですので以下のような手順になります。

  1. Vitis のインストール
  2. ザイリンクス ラインタイム (XRT; Xilinx Run Time) のインストール
  3. Vitis エンベデッドベースプラットフォーム (Embedded Base Platform) のインストール: ULTRA96V2_VITIS_2020_1.tar.gz

共通イメージに相当するものは下記の3番目のVitis エンベデッドベースプラットフォームの中に含まれています。手順1と2は前のセクション (ZCU102, ZC706 のプラットフォームのインストール)でも概要を説明していますので省略し、ここでは手順3について説明します。

Ultra96V2 のページ
図7: Ultra96V2 のページ

図7のスクリーンショットに示すように、Ultra96V2 の Vitis 用プラットフォームなどを提供しているサイトがあります。ここからリンクをたどってプラットフォームのファイルをダウンロードできます。このページの Reference Designs というタブをクリックします。

Vitis PetaLinux Platform と PreBuilt Example へのリンク
図8; Vitis PetaLinux Platform と PreBuilt Example へのリンク

Reference Designs のページをスクロールして見ていくと、図8のように Vitis PetaLinux Platform へのリンクがあります。なお Vitis PetaLinux Platform PreBuilt Example については次のセクションで説明します。

まずは、Platform をダウンロードします。Ultra96-V2 – Vitis Platform 2020+ (Sharepoint site) というリンクをクリックすると、図9のように 2020.2, 2020.1, 2019.2 の Platform へのリンクが現れますので、2020.1 をクリックして進みましょう。

Vitis Platform へのリンク
図9: Vitis Platform へのリンク
Vitis 2020.1 用ファイルへのリンク
図10: Vitis 2020.1 用ファイルへのリンク

図10のように Vitis 2020.1 用の各種ファイルがダウンロードできるようになっています。Vitis Platform をクリックしてさらに次へ進みましょう。

Ultra96-V2 Vitis 2020.1 Platform ファイルへのリンク
図11: Ultra96-V2 Vitis 2020.1 Platform ファイルへのリンク

図11のように各種 FPGA テストボード等の Vitis 2020.1 用 Platform ファイルがダウンロードできるようになっていますので、Ultra96-V2 用の Platform ファイル ULTRA96V2_VITIS_2020_1.tar.gz を見つけてダウンロードして下さい。

Vitis 2020.1 がデフォルトの /tools/Xilinx/Vitis/2020.1 にインストールされているなら、下記のようにダウンロードしたファイルを展開します。

cd /tools/Xilinx/Vitis/2020.1/platforms
tar -xvf <somewhere>/ULTRA96V2_VITIS_2020_1.tar.gz

これで /tools/Xilinx/Vitis/2020.1/platforms/ULTRA96V2 というディレクトリに Platform がインストールされます。先にも説明しましたが、この Platform ファイルの中に sysroot, rootfs, kernel image なども含まれていますので、ZC706 などのように common_images などを別途インストールする必要はありません。

ここまで、Vitis 2020.1 用の Ultra96-V2 用の Platform ファイルのダウンロードについて説明しました。Vitis 2020.2 用のファイルもダウンロードできますので、必要な方はそちらもダウンロードして使っていただけると思います。

Ultra96-V2 prebuilt vadd の実行

このブログの第1回でも試した Vector Add を Ultra96-V2 用に build したものが (prebuilt vadd) が入手可能ですので、その実行方法を説明します。

Ultra96-V2 が手元にあるけれども、FPGA テストボードの利用にはあまり慣れていないような場合、このセクションで説明する prebuilt vadd イメージを実行してみることをおすすめします (このようなボード扱いに慣れていらっしゃる場合は不要かもしれません)。実のところ、microSD カードからの Linux のブートは、いろいろとトラブルがつきものと感じています。prebuilt を使って確実に動作することを確認した上で、自分で build した回路の動作確認へと進むと良いのではないでしょうか。

prebuilt イメージのダウンロードと実行の準備

prebuilt の実行に必要なツール

エンベデッドプラットフォームではハードディスクやSSDの代わりに microSD カード (ZCU102 や ZC706 なら SD カード) を使います。ARM CPU で起動する Linux のブートローダやファイルシステムも microSD カードに入れておきます。また、ホストプログラムや FPGA カーネルイメージも microSD カード上にコピーしておくことになります。prebuilt のイメージにはこれらがすべて含まれています。

prebuilt された microSD カードのイメージをダウンロードして実行するるには以下のようなツールが必要となります。

  • シリアル通信ができるツール (Windows なら TeraTerm など)
  • SD カードへのイメージの書き込みができるツール (Windows なら Etcher など)

なお、prebuilt の実行に限れば、Windows だけでも (おそらく Mac でも) 作業可能です。

prebuilt イメージのダウンロード

前のセクションで示した図10を見ると Vitis_PreBuilt_Example というリンクがありますので、それをクリックします。図8の Ultra96-V2 – Vitis PetaLinux Platform 2020+ Vector Add (Sharepoint site) からリンクをたどってもよいのですが、結局は同じ図10にたどり着きますので、そこから Vitis_PreBuilt_Example をクリックすることになります。

Vitis 2020.1 Ultra96-V2 用 prebuilt イメージのダウンロード
図12: Vitis 2020.1 Ultra96-V2 用 prebuilt イメージのダウンロード

図12 のように各種 FPGA ボード用の prebuilt イメージがダウンロードできるようになっていますので、Ultra96-V2 用の 2020p1_ULTRA96V2_vadd.tar.gz をダウンロードして下さい。以下のように tar コマンドで展開すると、3つのファイルが生成されます。なお、最近の Windows 10 (1803以降) では、コマンドプロンプトで tar コマンドが使えるようです。

tar -xvf 2020p1_ULTRA96V2_vadd.tar.gz
  • README.txt
  • create_sd_card_image.sh
  • sd_card.img

prebuilt イメージの microSD カードへのコピー

sd_card.img が microSD カードのイメージファイルです。この中にブート可能な ARM 用 Linux ファイルシステムも prebuilt vadd も含まれています。README.txt に Linux のコマンドでのコピー方法が説明されています。

sudo dd bs=4M if=./sd_card.img of=/dev/sdb status=progress conf=fsync && sync && sync

また、このセクションで先に紹介したとおり、Windows では Etcher というツールを使って microSD カードへイメージをコピーすることもできます。

コピーが正常に終了すると、microSD カードには2つのパーティションが作成されます。

  1. 1.1GB Windows からアクセス可能 (FAT32 ファイルシステム)
  2. 2.2GB Windows からアクセス不可能 (ext4 ファイルシステム)

1番目のパーティション (Windows ならドライブ) を見ると、BOOT.BIN などの Linux を起動するためのファイルとともに、vadd や binary_container_1.xclbin といったホストプログラムや FPGA カーネルイメージも入っていることがわかります。

2番目のパーティションは Linux の ext4 ファイルシステムですので、正しく書き込まれていても Windows からは壊れたパーティションに見えてしまい「フォーマットしますか」などのメッセージが出てくることがあります。Windows ではアクセスできないファイルシステムでも、Etcher なら書き込んでしまうことは可能というわけです。

prebuilt イメージの実行

ここからは Ultra96-V2 付属の動作確認用 microSD カードを使ったテストと重複する作業もありますが、念のため順番に説明しておきます。

Ultra96-V2 の準備

Ultra96-V2 のケーブルの接続とスイッチ
図13: Ultra96-V2 のケーブルの接続とスイッチ

電源を入れる前に microSD カードを Ultra96-V2 のコネクタに挿入しておきましょう。図13の Ultra96-V2 の写真の右上、黄色の枠で囲ったディップスイッチ (SW3) は、1番を OFF, 2番を ON にして microSD からブートするようにします。おそらく購入時にはそのような設定になっていると思います。図13の写真のように電源と microUSB を接続します。外部の PC とは USB-JTAG のアダプタを介して microUSB で接続し、接続先の PC のターミナルアプリ (Windows の TeraTerm など) ではシリアルポートのスピード (baud rate) を115,200に設定します。

microSD カードからの Linux の起動

図13の写真の左下、赤丸で囲った電源スイッチを1, 2秒少し長めに押して電源を入れて下さい。正常に microSD から起動すれば、ボード上の各種 LED が点灯し、図14のように外部の PC のターミナルに Linux の起動メッセージが表示されるはずです。

Ultra96-V2 Linux の起動画面
図14: Ultra96-V2 Linux の起動画面

起動してしばらくすると、メッセージの出力が止まります。図14のように ERROR といった文字列も見えますので正常に起動したのかどうか少し不安になりますが、ENTER キーを入力すると図15のようにログインプロンプトが現れますので、正常に起動したことがわかります。 root ユーザでログインして下さい。

Ultra96-V2 Linux へのログイン
図15: Ultra96-V2 Linux へのログイン

Vector Addition の実行

ログインできましたら、Vector Addition を実行してみましょう。README.txt に書かれている通り、以下のようにコマンドを入力して下さい。

# cd /media/sd-mmcblk0p1
# export XILINX_XRT=/usr
# ./vadd binary_container_1.xclbin
Ultra96-V2 Linux 上での vadd の実行結果
図16: Ultra96-V2 Linux 上での vadd の実行結果

実行結果は図のようになり、大量のメッセージに埋もれてしまいそうですが、TEST_PASSED と出力されていますので、正常に実行できたことが確認できます。

Ultra96-V2 のシャットダウン

無事テストが終了して Ultra96-V2 の電源を切る際は、図14の写真で示した電源ボタンを押しても良いのですが、図16の最終行のようにコマンドラインから shutdown -h now というコマンドを実行することもできます。このコマンドを実行すると、最後に Power down というメッセージが表示され、Ultra96-V2 のボード上の各種 LED も消灯します。この状態になれば、PC で接続しているターミナルソフトを切断し、電源の AC アダプタや microUSB ケーブルなどを外しても大丈夫です。

エンベデッドプラットフォームでの CG 法の実行

エンベデッドプラットフォームである ZCU102, ZC706, Ulra96-V2 での CG 法の実行方法を説明します。以下のワークスペース名、プロジェクト名でプロジェクトを作成していきます。

  • ワークスペース名: cg_float_base3_workspace
  • プロジェクト名: cg_float_app

Vitis を起動してワークスペースやプロジェクトを作成するところはこのブログで前回まで説明してきた Vitis 2020.2 の例とほとんど変わりません。ここではエンベデッドプラットフォームで注意すべき点や 2020.2 と 2020.1 で異なる点を中心に説明します。

ワークスペースとプロジェクトの作成

プラットフォームの選択

Vitis のプラットフォームの選択
図17: Vitis のプラットフォームの選択

Ultra96V2 と ZC706, ZCU102 のプラットフォームをインストールしてあれば、図17のようにプラットフォームを選択できると思います。

Domain の設定 (ZCU102, ZC706 の場合)

ZC706 の Domain の設定
図18: ZC706 の Domain の設定

ZCU102 や ZC706 の場合は、図18のようにDomain の設定のウィンドウでの設定が必要です。例えば、このブログの「ZCU102, ZC706 のプラットフォームのインストール」の手順4「共通イメージのインストール」で説明した通り、ZCU102 の 共通イメージを /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1 にインストールしていれば、以下のように設定します。

  • Sysroot path: /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/sysroots/aarch64-xilinx-linux
  • Root FS: /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/rootfs.ext4
  • Kernel Image: /opt/common_images/2020.1/xilinx-zynqmp-common-v2020.1/Image

ZC706 の場合なら、共通イメージを /opt/common_images/2020.1/xilinx-zynq-common-v2020.1 にインストールしていれば、以下のように設定します。

  • Sysroot path: /opt/common_images/2020.1/xilinx-zynq-common-v2020.1/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi
  • Root FS: /opt/common_images/2020.1/xilinx-zynq-common-v2020.1/rootfs.ext4
  • Kernel Image:/opt/common_images/2020.1/xilinx-zynq-common-v2020.1/uImage

Domain の設定 (Ultra96-V2 の場合)

Ultra96-V2 の Domain の設定
図19: Ultra96-V2 の Domain の設定

Ultra96V2 の場合、図19のように Domain の設定のウィンドウで Sysroot path, Root FS, Kernel Image があらかじめ設定されていますので修正の必要はありません。図19ではプラットフォームのインストール先の一部を消していますが、デフォルトでは /tools/Xilinx になっているはずです。

CG 法のプログラムの build と実行

カーネルトップ関数の指定と build

プロジェクト名の設定や Empty Application の Template の指定など、U50 と同様に設定すれば、プロジェクトの初期設定は終了して、以下の図20のような初期画面が現れます。2020.1 と 2020.2 で違う点を中心に build までの手順を説明します。

ワークスペースとプロジェクトを作成した Vitis の初期画面
図20: ワークスペースとプロジェクトを作成した Vitis の初期画面

繰り返しになりますが、以下のワークスペース名、プロジェクト名であることを前提に説明を進めます。

  • ワークスペース名: cg_float_base3_workspace
  • プロジェクト名: cg_float_app

プロジェクト名が cg_float_app だと cg_float_app.prj というタブが中央に現れると思います。Hardware や Emulation-SW などの build configuration はこのウィンドウで設定します (2020.2 の場合は cg_float_app_kernels.prj で build 方法を選択しました)。

ソースファイルは cg_float_base3_workspace/cg_float_app/src に置きます。2020.2 と違い、ホストとカーネルのソースファイルは同じディレクトリに置くことに注意して下さい。前回までのブログと同じ CG 法のプログラムを build するなら github からダウンロードしたソースファイルをコピーして下さい。

カーネルトップ関数の指定は、図20の中央よりやや右下のアイコン (スクリーンショットでは赤丸をつけています) をクリックして行います。アイコンは 2020.2 と違いますが、指定方法はほぼ同じです。

カーネルトップ関数 kernel_func の指定
図21: カーネルトップ関数 kernel_func の指定

カーネルトップ関数を指定すると、図21のように kernel_func という関数名が表示されます。これで回路の合成の準備が整いましたので、ウィンドウの中央よりやや右上の Active build configuration を Hardware に設定し build して下さい。

SD カード (microSD カード) へのコピーと実行

回路の合成が終了したら、実機でのテストとなります。ZC706 や ZCU102 では SD カード、Ultra96V2 では microSD カードに ARM 用の Linux とホストプログラム、FPGA 用カーネルをコピーします。SD(microSD) カードのイメージは、cg_float_base3_workspace/cg_float_app/Hardware/package/sd_card.img として生成されます。なお、2020.2 の場合は cg_float_base3_workspace/cg_float_app_system/Hardware/package/sd_card.img になります。

イメージファイルを SD カードにコピーする手順は、Ultra96-V2 の prebuilt vadd と同様です。Windows で Etcher を使用するか、あるいは Linux で以下のコマンドを実行することで SD カードへコピーして下さい。

sudo dd bs=4M if=./sd_card.img of=/dev/sdb status=progress conf=fsync && sync && sync

SD カードの1番目のパーティションにはホストプログラム cg_float_app や FPGA カーネルイメージ binary_container.xclbin が入っています。このブログで使っている CG 法では係数行列データのファイル sym_sparse.mtx を使いますので、これも SD カードの1番目のパーティションにコピーします。

ただ、残念ながらこのコピーに失敗することがあります。その場合は以下のように対処すると正常にコピーできることがあるようです。

  1. cg_float_base3_workspace/cg_float_app/Hardware/package/sd_card には、1番目のパーティションに書き込まれたのと同じファイルが置かれています。ここに sym_sparse.mtx をコピーします。
  2. いったん、SD カードの1番目のパーティションを作り直します。Windows ならフォーマット、Linux ならファイルシステムを1度削除して作り直します。
  3. 作り直したパーティションに、1のディレクトリのファイルをコピーします。

もう少し上手い対処方法もあるかと思いますが、私自身はこのように対処することが多いです。

microSD カードへのコピーができましたら、Ultra96-V2 や ZC706 などの実機でテストすることになります。実機でのテストは Ultra96-V2 の prebuilt vadd の実行とほぼ同じ手順になりますので、そちらを参考にして下さい。

ZC706 のディップスイッチの設定
図23: ZC706 のディップスイッチの設定

なお、ZC706 では SD カードからのブートのためにディップスイッチを適切に設定して下さい。図23の写真で赤で囲った2か所のディップスイッチを設定して下さい。真ん中あたり、青い SW11 が OFF OFF ON ON OFF (下が OFF 上が ON) です。少し左の黒い SW4 は OFF ON です。

ZCU102 や ZCU104 は手元に実機がないので確認できませんでしたが、User Guide なども参照してディップスイッチを適切に設定して下さい。

Vitis Analyzer の起動

前回も説明しましたが、Hardware や Emulation-HW で build すると、Vitis Analyzer を起動してカーネルの各ループの遅延や LUT などの FPGA のリソースの使用状況が確認することできます。

Vitis Analyzer の起動
図22: Vitis Analyzer の起動

図22のようにプロジェクト名が cg_float_app の場合、2020.1 では cg_float_app → Emulation-HW (または Hardware) → … → Compiler Summary とたどって、Compiler Summary をダブルクリックして Vitis Analyzer を起動します。2020.2 の場合は cg_float_app_kernels → Emulation-HW (または Hardware) → … → Compiler Summary とやや違っていますのでご注意下さい。

CG 法の実行

前回 U50 で CG 法にいくつかの最適化を試みて、その実行時間見積もりを示しました。そのときは、疎行列の圧縮形式を ELL 形式とし、隣接するループを融合するのが有効であることがわかりました。同じプログラムで Ultra96-V2 でも実行してみたのが以下の表1です。前回と同じ github 上のプログラムを使っており、連立一次方程式の係数行列のサイズは16×16です。

U50 と Ultra96-V2 での CG 法の実行時間
表1: U50 と Ultra96-V2 での CG 法の実行時間
  • U50 20.2: U50 用に Vitis 2020.2 で build して実行 (前回と同じ)
  • U50 20.1: U50 用に Vitis 2020.1 で build して実行
  • U96 20.1: Ultra96-V2 用に Vitis 2020.1 で build して実行

疎行列の圧縮形式はすべて ELL です。ループ融合の違いで2通り試しています。

  • ELL+LF: spmv と dot, axpy2 と dot の2つループ融合を適用した場合
  • ELL+LF 改: spmv と dot のみループ融合を適用し、後者の axpy2 と dot は融合しない場合

表1に示した数値は Emulation-HW で build したときの実行時間や実行サイクル数の見積もりです。表の数値は上から順に以下の実行見積もりとなります。

  • Loop(ns): カーネルループの実行時間 (ns)
  • (cycles): カーネルループの実行サイクル数
  • cycles/iter: カーネルループの1反復あたりの実行サイクル数
  • 以下 axpy, spmv など: 各ループの実行サイクル数

Vitis 2020.2 では内積 (dot) を自動的に最適化しているようですが、そのために計算精度が低下し、Emulation-SW と Hardware とで結果がやや異なる原因となっていると思われます。この件はもう少し調べてみたいと思います。

Vitis 2020.1 では、dot の実行サイクル数が多いため、2つの dot それぞれを spmv や apxy2 のループを融合する ELL+LF の方が高速です。この 2020.1 で U50 と Ultra96-V2 を比べると、実行サイクル数には大きな差はありません。実行時間は U50 で 17.55μs, Ultra96-V2 で 39.9μs となっていて、それぞれの動作周波数 300MHz と 150MHz の差が実行時間の差に表れています。

このように組込み機器で数十マイクロ秒でこのサイズの CG 法が実行できていますが、実用的には消費電力も含めて総合的に評価することになります。また、上の表には載せていませんが、ホストプログラムからの FPGA カーネルの呼び出し時間が 150ms 程度はかかっていますので、この点も考慮する必要があります。

今回は試していませんが、Ultra96-V2 でも動作周波数を高くすることは可能です。ただ、演算のパイプライン段数が多くなり、必ずしも高速化に結びつくとは限りません。

まとめ

今回は、エンベデッドプラットフォームである ZC706, ZCU102, Ultra96-V2 での Vitis と関連ソフトのインストールや FPGA でのカーネルの実行方法を説明しました。いろいろなツールを使うのは大変だったりしますが、各メーカ様のツールの改良や情報の公開も進んでいますので、HLS で組込み用の FPGA を扱うという手法も広まっていくのではないかと期待しています。

今回はダウンロードしたプラットフォームを使いましたが、プラットフォームを自分でカスタマイズすることもできます。ACRi ブログでも以下のように Ultra96-V2 のプラットフォームを作成する手順が説明されていますので、試してみてはいかがでしょうか。

次回は最終回となります。Ultra96-V2 にしろ、U50 にしろ、今まで紹介した例では LUT などの FPGA のリソースをわずかしか使っていません。次回は積極的にリソースを使うとどのくらい高速化できるのかを試してみます。また、もっと大規模なデータサイズの問題も扱ってみようと思います。

広島市立大学 窪田昌史

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