FC2カウンター FPGAの部屋 TVM_VTA
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる2

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる1”の続き。

Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみようということで、Darknet YoloV3-tiny 推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行することができた。今回は、”Deploy Pretrained Vision Detection Model from Darknet on VTA”の記述を DeepL 翻訳で訳して、動作を少しは確認してみよう。

ダークネットで事前学習した視覚検出モデルをVTAに展開する
最初の文章を DeepL で翻訳して引用する。

このチュートリアルでは、Darknet YoloV3-tiny推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行する方法について、エンドツーエンドデモを提供します。このチュートリアルでは、量子化(VTAはint8/32推論のみをサポート)とグラフパッキング(コアでのテンソル化を可能にするため)を行い、ハードウェアターゲット向けに計算グラフを調整するフロントエンドコンパイラとしてのRelayを紹介します。


pip3 で cffi と opencv-python をインストールする必要があるとのことだが、私の Ubuntu 18.04 にはインストールしてあったようでインストールする必要はなかった。
pip3 install cffi
pip3 install opencv-python


最初に deploy_detection.py のライセンス部分を示す。これから、deploy_detection.py の多用する。
TVM_VTA_175_220712.png

依存関係のインストール
インポートするパッケージを示す。
TVM_VTA_187_220714.png

モデル名からyolo netの設定ファイル、重みファイル、ダークネット・ライブラリ・ファイルのダウンロードを行う。
TVM_VTA_189_220714.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

cfg_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.cfg
weights_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.weights


ホーム・ディレクトリの .tvm_test_data/darknet ディレクトリにファイルが生成されていた。
TVM_VTA_190_220714.png

YOLO のカテゴリー名の coco.name と arial.ttf をダウンロード
TVM_VTA_191_220714.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

coco_path = /home/masaaki/.tvm_test_data/data/coco.names
font_path = /home/masaaki/.tvm_test_data/data/arial.ttf


ホーム・ディレクトリの .tvm_test_data/data ディレクトリにファイルが生成されていた。
TVM_VTA_192_220714.png

プラットフォームとモデル・ターゲットの定義
TVM_VTA_193_220714.png

リモート実行の取得
ターゲットが'pynq'または他のFPGAバックエンドの場合、FPGAとランタイムを再設定する。それ以外の場合、ターゲットが 'sim' であれば、ローカルに実行する。
TVM_VTA_194_220714.png

推論グラフ・エクゼキュータの構築
DeepL 翻訳を引用する。

Gluon model zooからVisionモデルを取得し、Relayでコンパイルします。コンパイルの手順は

1. フロントエンドはMxNetからRelayモジュールに変換。

2. 8ビット量子化の適用:ここでは、CPUのfp32で実行される最初のconv層とdense層をスキップしています。

3. グラフパッキングを行い、テンソル化するためのデータレイアウトを変更する。

4. 定数折りたたみを行い、演算子の数を減らす(例:バッチノルム乗算をなくす)。

5. オブジェクトファイルへのリレービルドを行う。

6. オブジェクトファイルをリモート(FPGAデバイス)にロードする。

7. グラフエクゼキュータmを生成する。


TVM_VTA_195_220714.png
TVM_VTA_196_220714.png

画像検出の推論の実行
テスト画像をダウンロードし、画像に対して推論を実行する。
TVM_VTA_197_220714.png
TVM_VTA_198_220714.png

ターミナルのログを貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/pynq/test_program_rpc.py
(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_detection.py 
cfg_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.cfg
weights_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.weights
coco_path = /home/masaaki/.tvm_test_data/data/coco.names
font_path = /home/masaaki/.tvm_test_data/data/arial.ttf
Reconfigured FPGA and RPC runtime in 3.17s!
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
yolov3-tiny inference graph built in 19.06s!

Performed inference in 658.92ms (std = 0.37) for 1 samples
Average per sample inference time: 658.92ms

  1. 2022年07月14日 05:03 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる1

Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみよう。

Deploy Pretrained Vision Detection Model from Darknet on VTA”は Darknet YoloV3-tiny 推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行する。

Deploy Pretrained Vision Detection Model from Darknet on VTA”から deploy_detection.py をダウンロードした。
TVM_VTA_181_220712.png

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで deploy_detection.py を実行した。
python3 vta/tests/python/integration/deploy_detection.py

deploy_detection.py を実行すると、犬と人間と馬の画像が表示されたが、それを閉じても””Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1”と同様にソフトウェアが進まなくなった。
そこで、deploy_detection.py の 265, 266 行目をコメントアウトした。
これでもう一度、deploy_detection.py を実行した。
TVM_VTA_183_220712.png
TVM_VTA_184_220712.png

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_detection.py 
Reconfigured FPGA and RPC runtime in 2.88s!
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:32] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:32] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
yolov3-tiny inference graph built in 18.91s!

Performed inference in 660.54ms (std = 2.14) for 1 samples
Average per sample inference time: 660.54ms


画像検出結果が表示された。
TVM_VTA_185_220712.png

PYNQ-Z1 の表示を示す。
TVM_VTA_186_220712.png

xilinx@pynq:~$ cd tvm
xilinx@pynq:~/tvm$ sudo ./apps/vta_rpc/start_rpc_server.sh
INFO:RPCServer:bind to 0.0.0.0:9091
INFO:RPCServer:connection from ('192.168.3.10', 43720)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:RPCServer:Finish serving ('192.168.3.10', 43720)
INFO:RPCServer:connection from ('192.168.3.10', 43722)
INFO:root:Skip reconfig_runtime due to same config.
INFO:RPCServer:Finish serving ('192.168.3.10', 43722)
INFO:RPCServer:connection from ('192.168.3.10', 43724)
INFO:root:Skip reconfig_runtime due to same config.
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmp9vv5ioxf/graphlib.tar

  1. 2022年07月13日 03:22 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる2

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1”の続き。

前回は、”Deploy Pretrained Vision Model from MxNet on VTA” からダウンロードした deploy_classification.py を実行して成功した。今回は、”Deploy Pretrained Vision Model from MxNet on VTA” の記述を DeepL 翻訳で訳して、動作を少しは確認してみよう。

最初の文章を DeepL で翻訳して引用する。

このチュートリアルでは、ImageNet分類推論をVTAアクセラレータ上で実行し、ImageNet分類タスクを実行する方法について、エンドツーエンド・デモを提供します。このチュートリアルでは、量子化(VTAはint8/32推論のみをサポート)とグラフパッキング(コアでのテンソル化を可能にするため)を行い、ハードウェアターゲットに合わせた計算グラフを作成するフロントエンドコンパイラとしてRelayが紹介されています。


次は pip3 で mxnet をインストールしているようだ。やはり、mxnet をインストールする必要があるようだ。

deploy_classification.py のコードを引用していく。deploy_classification.py のライセンスを貼っておく。
TVM_VTA_175_220712.png

依存関係のインストール
argparse, json, os, requests, sys, time や mxnet, tvm, vta などのライブラリを呼び出している。
TVM_VTA_173_220712.png

プラットフォームとモデルのターゲットの定義
resnet18_v1 から resnet101_v2 のパラメータを pack_dict ディクショナリに登録する。
resnet18_v1 モデルを選択した。
TVM_VTA_174_220712.png

実行リモートの取得
ターゲットが'pynq'の場合、FPGAとランタイムを再設定する。それ以外の場合、ターゲットが 'sim' であれば、ローカルに実行するそうだ。
TVM_VTA_176_220712.png

推論グラフエクゼキュータの構築
DeepL 翻訳を引用する。

Gluon model zooからVisionモデルを取得し、Relayでコンパイルします。コンパイルの手順は

1. フロントエンドはMxNetからRelayモジュールに変換。

2. 8ビット量子化の適用:ここでは、CPUのfp32で実行される最初のconv層とdense層をスキップしています。

3. グラフパッキングを行い、テンソル化するためのデータレイアウトを変更する。

4. 定数折りたたみを行い、演算子の数を減らす(例:バッチノルム乗算をなくす)。

5. オブジェクトファイルへのリレービルドを行う。

6. オブジェクトファイルをリモート(FPGAデバイス)にロードする。

7. グラフエクゼキュータmを生成する。


TVM_VTA_177_220712.png
TVM_VTA_178_220712.png

画像分類の推論の実行
ImageNetの画像サンプルに対して分類を行う。カテゴリファイル、synset.txt、入力テスト画像をダウンロードするだけだそうだ。
TVM_VTA_179_220712.png
TVM_VTA_180_220712.png

結果を下に示す。

resnet18_v1 inference graph built in 26.26s!

Performed inference in 408.14ms (std = 2.18) for 1 samples
Average per sample inference time: 408.14ms

resnet18_v1 prediction for sample 0
    #1: tiger cat
    #2: Egyptian cat
    #3: tabby, tabby cat
    #4: lynx, catamount
    #5: weasel

  1. 2022年07月12日 04:10 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1

Deploy Pretrained Vision Model from MxNet on VTA”をやってみよう。今回は、普通に”Deploy Pretrained Vision Model from MxNet on VTA” からダウンロードした deploy_classification.py を実行してみよう。

Deploy Pretrained Vision Model from MxNet on VTA”から deploy_classification.py をダウンロードし、tvm/vta/tests/python/integration ディレクトリにセーブした。
TVM_VTA_172_220711.png

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
結果はエラーで原因は mxnet モジュールが無いということだった。
TVM_VTA_167_220710.png

pip3 で mxnet モジュールをインストールする。
pip3 install mxnet
TVM_VTA_168_220710.png

もう一度、ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
TVM_VTA_169_220710.png

ここで、ウインドウが表示されて、猫の写真が表示された。
TVM_VTA_170_220710.png

その後は何も実行されなかった。猫のウインドウを消しても何も進まない。
実行ログを示す。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_classification.py 
Reconfigured FPGA and RPC runtime in 2.89s!
Downloading /home/masaaki/.mxnet/models/resnet18_v1-a0666292.zipefe2e9c7-23b8-4e5f-9eb8-62f6771a59a7 from https://apache-mxnet.s3-accelerate.dualstack.amazonaws.com/gluon/models/resnet18_v1-a0666292.zip...
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
vta/tests/python/integration/deploy_classification.py:212: DeprecationWarning: legacy graph executor behavior of producing json / lib / params will be removed in the next release. Please see documents of tvm.contrib.graph_executor.GraphModule for the  new recommended usage.
  graph, lib, params = relay.build(
resnet18_v1 inference graph built in 27.19s!


deploy_classification.py の猫のウインドウ表示部分をコメントアウトした。
253 行目と 254 行目をコメントアウトした。
TVM_VTA_171_220710.png

これで、ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
TVM_VTA_172_220710.png

tiger cat と判定された。

resnet18_v1 inference graph built in 26.26s!

Performed inference in 408.14ms (std = 2.18) for 1 samples
Average per sample inference time: 408.14ms

resnet18_v1 prediction for sample 0
    #1: tiger cat
    #2: Egyptian cat
    #3: tabby, tabby cat
    #4: lynx, catamount
    #5: weasel

  1. 2022年07月11日 05:00 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる4

”Simple Matrix Multiply”をやってみる3”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”の”行列の乗算”から”テンソル化”までを書いた。今回は、”TVMコンパイル”、”関数の実行”、”正しさの検証”を行った。

TVM コンパイル
スケジュールが終わったので、TVM 関数にコンパイルする。
TVM_VTA_164_220710.png

関数の実行
コンパイルされたTVM関数は、簡潔なC APIを使用しており、どの言語からも呼び出すことができるそうだ。
TVMはpythonで配列のAPIを提供し、迅速なテストとプロトタイピングを支援します。この配列APIはDLPack標準に基づいているそうだ。

モジュールを実行する手順
1. リモート・コンテキストを作成する(Pynq でもリモート実行用)
2. tvm.nd.array でデータをフォーマットする
3. f() で計算を実行する
4. numpy()は結果の配列を解釈可能な形式にコピーして返す


TVM_VTA_165_220710.png

正しさの検証
numpyで乗算を計算し、VTA の行列の乗算の出力が本当に正しいかどうかを検証する。
TVM_VTA_166_220710.png

Successful matrix multiply test!

と表示された。乗算は正しい。

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_nd.numpy().shape = (1, 16, 1, 16)
[[[[ -98   45 -126    8  101   -6 -124   82  -19  -39   47   53  -74
     -76   -4   84]]

  [[ 120  -69 -106   89 -121   -3  125  103  -51   61  -42  -54  127
     -80 -103   -1]]

  [[  17  103   63   -8 -126    9  -79 -112 -118   17  104  -14  -69
      62 -100  -38]]

  [[ 125  -82   95  115   27    0  -19   21   -8  -28   35  101 -109
     -27  -72 -123]]

  [[  72  -26   34  101  -64   29  -83    8   23  -62  111   52 -117
     -46   50 -118]]

  [[  58  -47 -113   62   29  -78 -101   62 -116  -25   22  -84   37
     -40  -65    4]]

  [[-109   52  -33 -114 -118  -93  106   73  102 -122  -88  -98   64
     -44  -36  -52]]

  [[  84   33  -17  -19  -71  104   67    7 -102   90   91    8 -111
       4  -91   48]]

  [[ -20  116   79   41    8    8   62  -71  -64  -25  -78   13  -72
     -75  -88  -56]]

  [[-110   11  -38  -58  -77  -34   42   69   98  -51  -95  -53  -21
      75  -81    3]]

  [[  78  102   91  -73  -69  -47  -86   16  122   91 -105   -8  106
      37   82 -103]]

  [[ -87   84  116  -25  -64   67  -70   85   36   -3   65   59   14
      26   93  -16]]

  [[  11  -37 -104   -5   43  -94  -78  -71   37  -44  -37 -103  -34
     110   84  -83]]

  [[ 109   81   63   65  -44  122  -77  -57  -24  -72   -4  -99   95
     -26   86   46]]

  [[  92 -127  -55   -1  -46  -79  -18  114   46   64   55  -90  -83
     -93  -79  -77]]

  [[ -32  -31    8   21  -43  -71   50 -126   59   63   69   43  -78
     112   18  116]]]]

  1. 2022年07月10日 03:51 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる3

”Simple Matrix Multiply”をやってみる2”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”に沿って 1 つ 1 つコードを見ながら実行することにした。”RPC 設定”から”データのレイアウト”までを書いた。今回は、”行列の乗算”から”テンソル化”までを書いた。

なお、翻訳には DeepL 翻訳を使用している。

行列の乗算
DeepL 翻訳を貼っておく。

これで行列の乗算の結果テンソルCを別の計算操作で記述する準備が整った。計算関数はテンソルの形と、テンソルの各位置の計算規則を記述したラムダ関数を受け取る。

行列の乗算を実装するために、ラムダ関数には入力チャンネルの次元軸に対する縮小式が必要である。削減式を作成するには,te.reduce_axisで削減軸を宣言し,削減範囲を取り込みます.te.sumは削減する式と削減軸を取り込み,宣言した範囲内のすべてのkに対する値の総和を計算します.

このリダクションは32ビットenv.acc_dtypeアキュムレータデータ型に対して実行される必要があることに注意してください。

このフェーズでは,計算をどのように行うかを宣言しているだけなので,計算は行われません.


TVM_VTA_157_220709.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_buf = Tensor(shape=[1, 16, 1, 16], op.name=C_buf)


結果のキャスト
乗算が終了したら、VTA で計算した結果をメイン・メモリに転送する。
入力活性化データ型(env.inp_dtype)へのタイプ・キャストを行う。
計算宣言部分は終了。
TVM_VTA_158_220709.png

計算のスケジューリング
TVM ではスケジュールという計算の実装をする必要がある。
DeepL 翻訳を貼っておく。

スケジュールとは、元の計算に対する変換の集合であり、正しさに影響を与えることなく計算の実装を変換するものである。この簡単なVTAプログラミングのチュートリアルは、元のスケジュールをVTAハードウェアプリミティブにマップダウンする基本的なスケジュール変換を示すことを目的としています。


デフォルトのスケジュール
スケジュール構築後、デフォルトでの C を計算するスケジュールを示す。
TVM_VTA_160_220709.png

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(A_buf: Pointer(global int8), int8, [256]), storage_scope = global;
  allocate(B_buf: Pointer(global int8), int8, [65536]), storage_scope = global;
  allocate(C_buf: Pointer(global int32), int32, [256]), storage_scope = global {
    for (i1: int32, 0, 16) {
      for (i3: int32, 0, 16) {
        let cse_var_1: int32 = ((i1*16) + i3)
        A_buf_1: Buffer(A_buf, int8, [256], [])[cse_var_1] = A[cse_var_1]
      }
    }
    for (i0: int32, 0, 16) {
      for (i1_1: int32, 0, 16) {
        for (i2: int32, 0, 16) {
          for (i3_1: int32, 0, 16) {
            let cse_var_2: int32 = ((((i0*4096) + (i1_1*256)) + (i2*16)) + i3_1)
            B_buf_1: Buffer(B_buf, int8, [65536], [])[cse_var_2] = B[cse_var_2]
          }
        }
      }
    }
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [])[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          for (ki: int32, 0, 16) {
            let cse_var_3: int32 = ((co*16) + ci)
            C_buf_1[cse_var_3] = (C_buf_1[cse_var_3] + (cast(int32, A_buf_1[((ko*16) + ki)])*cast(int32, B_buf_1[((((co*4096) + (ko*256)) + (ci*16)) + ki)])))
          }
        }
      }
    }
    for (i1_2: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_4: int32 = ((i1_2*16) + i3_2)
        C[cse_var_4] = cast(int8, C_buf_1[cse_var_4])
      }
    }
  }
}


DeepL 翻訳を貼っておく。

このスケジュールは理にかなっていますが、VTAにコンパイルすることはできません。正しいコード生成のためには、スケジューリングプリミティブとコードアノテーションを適用して、スケジュールをVTAのハードウェアイントリニックスに直接落とせるようなものに変換する必要があるのです。それらは以下の通りです。

・DMAコピーオペレーションは、グローバルにスコープされたテンソルを受け取り、それをローカルにスコープされたテンソルにコピーする。

・行列の乗算を実行するテンソル演算。


バッファのスコープ
バッファのスコープを設定して、バッファが VTA のオンチップ SRAM キャッシュに格納されることを TVM に通知する。
A_buf が VTA のオンチップ入力、B_buf が VTA のオンチップ重み、C_buf が VTA のオンチップ・アキュムレータ・メモリに格納されることを TVM に通知する。

DeepL 翻訳を貼っておく。

VTAのオンチップSRAM

VTAは3種類のメモリスコープを持ち、それぞれが異なるオンチップSRAMバッファに対応しています。

env.inp_scope : 入力バッファ。env.inp_dtype型の形状(env.BATCH, env.BLOCK_IN)の入力マトリクスを格納するリードオンリーのSRAMバッファです。入力バッファには、2 ^ LOG_INP_BUFF_SIZE行列要素(vta_config.jsonファイルで指定されたもの)が格納されます。

env.wgt_scope : env.wgt_dtype 型の形状 (env.BLOCK_OUT, env.BLOCK_IN) のウェイト行列を格納する読み込み専用の SRAM バッファです。ウェイトバッファは2 ^ LOG_WGT_BUFF_SIZE行列要素を含みます。

env.acc_scope : env.acc_dtype 型の形状 (env.BATCH, env.BLOCK_OUT) のアキュムレータ行列を格納するリード/ライト SRAM バッファです。アキュムレータバッファはVTAの汎用レジスタファイルであり,畳み込みや行列の乗算の中間結果や,プーリング,バッチ正規化,活性化レイヤの中間結果などを保持します.アキュムレータバッファは、2 ^ LOG_ACC_BUFF_SIZE の行列要素を含みます。


TVM_VTA_161_220709.png

DMA 転送
DRAMのデータを VTA のオンチップ・バッファに転送するために DMA 転送のスケジュールを組む。
これは、行列の乗算を実行する計算ループにバッファのコピーをネストするcompute_atスケジュールプリミティブを使用して実現することができるそうだ。
dma_copy プラグマを挿入して、コピー操作が DMA 転送で実行されることをコンパイラに示す。
TVM_VTA_162_220709.png

テンソル化
DeepL 翻訳を貼っておく。

スケジュール変換の最後のステップは、スケジュールにテンソル化を適用することである。テンソル化はベクトル化に類似しているが、その概念をより高次元の計算単位に拡張するものである。その結果、テンソル化はデータレイアウトの入力プレースホルダーを宣言するときに説明したように、データレイアウトの制約を課すことになる。我々はすでにテンソルをタイル状に配置したので、次に行うべきことはテンソル化に対応するためのループの再順序付けである。

ここでは、一番外側の縮小軸をずっと外側に移動することにした。このため、まず入力チャネル、次にバッチ次元、最後に出力チャネルを反復処理することになる。最後に、テンソル化スケジューリングプリミティブtensorizeを、最内周の行列乗算テンソルブロックの外軸に沿って適用する。最終的なスケジュールはVTAランタイムJITコンパイラによるコード生成に対応できるように出力される。


TVM_VTA_163_220709.png

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(C_buf: Pointer(local.acc_buffer int32), int32, [256]), storage_scope = local.acc_buffer;
  allocate(A_buf: Pointer(local.inp_buffer int8), int8, [16]), storage_scope = local.inp_buffer;
  allocate(B_buf: Pointer(local.wgt_buffer int8), int8, [16]), storage_scope = local.wgt_buffer {
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [], scope="local.acc_buffer", align=16)[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          attr [IterVar(i0: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3: int32, 0, 16) {
            A_buf_1: Buffer(A_buf, int8, [16], [], scope="local.inp_buffer", align=16)[i3] = A[((ko*16) + i3)]
          }
          attr [IterVar(i0_1: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3_1: int32, 0, 16) {
            B_buf_1: Buffer(B_buf, int8, [16], [], scope="local.wgt_buffer", align=256)[i3_1] = B[((((co*4096) + (ko*256)) + (ci*16)) + i3_1)]
          }
          for (ki: int32, 0, 16) {
            let cse_var_1: int32 = ((co*16) + ci)
            C_buf_1[cse_var_1] = (C_buf_1[cse_var_1] + (cast(int32, A_buf_1[ki])*cast(int32, B_buf_1[ki])))
          }
        }
      }
    }
    attr [IterVar(i0_2: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
    for (i1: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_2: int32 = ((i1*16) + i3_2)
        C[cse_var_2] = cast(int8, C_buf_1[cse_var_2])
      }
    }
  }
}

  1. 2022年07月09日 04:29 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる2

”Simple Matrix Multiply”をやってみる1”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”からダウンロードした matrix_multiply.py をそのまま実行して成功した。今回は、”Simple Matrix Multiply”に沿って 1 つ 1 つコードを見ながら実行してみよう。

なお、翻訳には DeepL 翻訳を使用している。

RPC 設定
Get Started with VTA”では、””Get Started with VTA”をやってみる1”に示すように、”ライブラリ読み込み”、”VTAパラメータの読み込み”、”FPGA プログラミング”が”Simple Matrix Multiply”の”RPC 設定”になっているようだ。
matrix_multiply.py のコードを引用する。
TVM_VTA_150_220707.png
TVM_VTA_151_220707.png

演算のための宣言
Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_153_220708.png

上図を説明すると、メインメモリに入力用配列 A, B を定義する。
VTA のオンチップ・バッファの中間配列 A_buf, B_buf を定義する。
A_buf, B_buf の行列の乗算を行って、積行列 C_buf を生成する。
積行列 C_buf を C にキャストして代入する。つまり、DRAM へのコピーを行う。

データのレイアウト
VTAテンソルコアが要求するデータレイアウトに合わせて、プレース・ホルダー配列A、Bをタイル状のデータフォーマットで記述するそうだ。

データタイリング
ここからは DeepL 翻訳の訳文をそのまま引用するが、VTA テンソルコアの部分は、配列の演算をする場合は、重みは転置しないとおかしいと思うのだけれどどうだろうか?

アクセラレータをターゲットとするとき、複雑さの原因の一つは、データレイアウトがアクセラレータ設計によって課されるレイアウトと一致することを確認することです。VTAは、下図に示すように、活性化行列と重み行列の間で1サイクルあたり1回の行列-行列演算を行い、その結果行列をアキュムレータ行列に追加するテンソルコアを中心に設計されている。


Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_154_220708.png

その行列と行列の掛け算の次元は、設定ファイル vta_config.json で指定される。活性化行列は(BATCH, BLOCK_IN)、転置ウエイト行列は(BLOCK_OUT, BLOCK_IN)の形状をしており、結果として出力行列は(BATCH, BLOCK_OUT)の形状をしていると推察される。従って、VTAが処理する入力テンソルおよび出力テンソルは、前述の次元に従ってタイリングされる必要がある。


下図は、元々(4, 8)の形状を持つ行列に対して、データのタイリングを行った場合の影響を示している。(2,2)のタイル形状でタイル化することで、各タイル内のデータが連続することが保証される。その結果、タイル化されたテンソルは(2, 4, 2, 2)の形状を持つことになる。


Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_155_220708.png

データの種類
VTA のテンソルコアの内部タイルの次元に合わせるだけでなく、VTA が期待する特定のデータ型に合わせることも重要だそうだ。
VTA は固定小数点データ型のみのサポートで、整数ビット幅は vta_config.json ファイルで指定されている。
アクティビティ(入力かな?)は INP_WIDTH で、重みは WGT_WIDTH で指定されている。アキュムレータ・データ型(これは出力の整数ビット幅かな?)は ACC_WIDTH で指定されている。
現在の vta_config.json ファイルで指定されている値は、以下の通り
LOG_INP_WIDTH が 3 つまり、2^3 で 8 ビット幅
LOG_WGT_WIDTH が 3 つまり、2^3 で 8 ビット幅
LOG_ACC_WIDTH が 5 つまり、2^5 で 32 ビット幅

env.inp_dtypeとenv.wgt_dtypeはすべて 8 ビット整数、env.acc_dtype は標準の 32 ビット整数になるそうだ。
TVM_VTA_156_220708.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

env.BATCH = 1
env.BLOCK_OUT = 16
env.BLOCK_IN = 16
A = Tensor(shape=[1, 16, 1, 16], op.name=A)
B = Tensor(shape=[16, 16, 16, 16], op.name=B)
A_buf = Tensor(shape=[1, 16, 1, 16], op.name=A_buf)
B_buf = Tensor(shape=[16, 16, 16, 16], op.name=B_buf)
C_buf = Tensor(shape=[1, 16, 1, 16], op.name=C_buf)

  1. 2022年07月08日 05:01 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0
»