2017年8月12日土曜日

TE0720 No.4 (BNN-PYNQを動かしてみる 2)

TE0720でBNN-PYNQを動かすことが出来た。
以下は前回に続いてBNN-PYNQが動くまでの記録。

gdb (GNU debugger)で例外が出る原因を調べてみた。
例外が発生しているのはシェアードライブラリ(python_hw-cnv-pynq.so)の中であり、これはpythonからダイナミックリンクされるのでpythonごと gdb で追えば何か判るのではないかと考えた。

run ./x.py としてx.pyスクリプトを実行させると、以下のようにSIGILLシグナルを受けて停止したが、かまわず cont と打って実行を継続させた。

すると、あのterminate called after throwing an instance of 'char const*'というメッセージが表示され、SIGABRTシグナルを受けてプログラムが停止した。ここでバックトレースを確認した。


関数FoldedMVInitの400行目で例外がthrowされているようだ。python_hw-cnv-pynq.soはデバッグ用の情報も付いているようなので、gdbを一旦終了しBNN-PYNQのソースファイルを/home/xilinx/test-newswg/下に展開してgdbを起動して上述と同じところまで操作した。
次に関数 FoldedMVInitをリスト表示し400行目付近を見てみた。

accelBuffer用の領域確保に失敗して例外を投げているようだ。そこで397行目にブレークポイントを設定してプログラムを再実行した。



accelBufInの確保も失敗してnullポインタが返ってきているようだ。
そこで、今度はallocAccelBuffer関数の中を追ってみることにした。

allocAccelBuffer内部では引数をcma_allocに渡してcma領域を確保していた。cma_allocはContiguous memory allocatorでカーネル内部に物理アドレスが連続したバッファを確保するための関数らしい。今の場合は30MB分の連続領域を確保しようとしている。ステップ実行したところ、cma_allocからnullポインタが返っていることが判った。

現在のOSのcma領域がどうなっているか確認したところ、そもそも全体でも16MB分の領域しかないことが判った。


そこで容量を128MBに増やしてみた。


増量して、cma_allocをコールする直前での空き容量を見ると70MBあるので今度は大丈夫の筈だが、ステップ実行してcma_allocからの戻り値を見るとnullポインタが返されていた。


そこで、今度はcma_allocの中を追ってみることにした。cma_allocのソースファイルは無いので、アセンブラレベルでのステップ実行になったが、その結果 ioctl コールでエラーが返っていることが判った。






現状のカーネルはpetalinuxのカーネルでバージョンは4.9.0なのだが、もしかしたらcma_allocのioctlコールの引数仕様がカーネル4.9.0で動作しているデバイスドライバの仕様と違っているのかも知れない。そこで、カーネルをPYNQのカーネルに代えてみることにしたのだが、カーネルのファイル名やファイル形式、デバイスツリーのファイル名等がpetalinuxとPYNQとでは異なっており、そのためにu-bootも変更することになってしまった。ところが、Xilinxのgitリポジトリからu-bootをcloneしてビルドして動かしてみたところ、mmcを認識しない。。。仕方がないのでZYBOのu-bootを使うことにした。


上記構成のSDカードにして起動し x.py を実行したところ例外は発生しなくなった。

PYNQのカーネルのバージョンは4.6.0だった。4.6.0と4.9.0ではcma_alloc関連の仕様が変わっているのかも知れない。また、4.9.0ではFPGAのコンフィグレーションのFPGA managerが追加になっているのでそれに関連してxdevcfgも変わっている可能性もある。。 ともあれ、例外が発生しなくなったのでjupyter notebookでCifar10.ipynbを実行してみた。


実行できた!!

で、推論をハードウェアで実行(PLにダウンロードして実行)した場合とソフトウェアのみで実行した場合との差は801108 / 3199 = 250倍となった。 ARMのシングルコアのみで実行するよりも推論部をPLにダウンロードしてハードで実行させると250倍高速に実行できた、ということだ。本物のPYNQボードだとどの位なんだろうか?





Road-Signs-Batch(道路標識の識別)も実行してみた。


こちらも実行できた。




カーネル 4.9.0でioctlがなぜsyscall エラーになるのかという点など、まだ頭の中に?マークがあるが、なんとか動くようになったので良かった。 ワーイ \(^_^)/


0 件のコメント:

コメントを投稿

自作CPUで遊ぶ 25

まだ制御ソフトが完成していないので今まではスピンドルを移動するために一々簡単なプログラムを書いて移動させていたのだが、非常に面倒なのでCNCペンダント的なものを作ることにした。 右側の縦に2つ並んでいるスイッチ...