雑多な趣味の記録帳

tom01h.exblog.jp

タグ:tiny-dnn ( 48 ) タグの人気記事

SystemC 入門

前に書きました が、畳み込みのインデックス生成に SystemC を使ってみようと思っています。
本格始動はスキーの試験が終わってからの予定ですが、ちょっとだけ試行。

ここ を参考に入門してみます。当然ですが、古い情報しか無いんですよね。
ダウンロードサイトは変わっていて、ここ からダウンロードできます。

インストール先はバージョンに合わせて変更しています。
../configure --prefix=/usr/local/systemc-2.3.3

とりあえず次の2つを試してみました。

HelloWorld - 始めの一歩
クロックカウンタを作る - モジュール定義を覚える

Makefile は 以下の2行の変更が必要でした。

SYSTEMC = /usr/local/systemc-2.3.3
TARGET_ARCH = linux64

さらにライブラリを見やすいところにコピーする必要もありました。
もう少しスマートな方法ありそうですが…

cp /usr/local/systemc-2.3.3/lib-linux64/libsystemc-2.3.3.so /usr/lib/

あっさりシミュレーションが流れ、カウンタの方は VCD 波形も生成されます。
畳み込みのインデックス生成くらいなら、特に文法の勉強しないで上の改変だけで出来るかな?

あとは HLS で Verilog を生成して、シミュレーションを流してみれば OK ?

by tom01h | 2019-02-07 21:57 | Trackback | Comments(0)

今頃、なぜか SystemC

tiny-dnn アクセラレータを作っていて、やっぱりサンプルコントローラ部(畳み込みのためのインデックス生成部)は C言語で書けたらいいなと思っています。
でも、コア部分はまだまだ Verilog で書きたいし、全体的な動作も紙に書いた通りのサイクル数で動いてほしい。
そんなわけで、畳み込みの 5重くらいのループで配列のインデックスだけを計算して出力するモジュールを C言語で書きたいんです。
今回は Verilog で書いて結構大変な目にあいましたし…

HLS で色々考えてみたんだけど、そもそも C言語で毎サイクル変数(インデックス)の値を出力って記述が出来るわけないし…
そんな中で検索に引っかかってきた懐かしいキーワードが SystemC です。
Vivado HLS でもサポートしているみたいだし、試してみる価値はあるかな? 解説本とか軒並み廃刊だな…
でも、多分 ここ に知りたいことのほとんどが書かれていると思われる。もう一個

ちなみにソフトなら
for(i=0;i<10;i++)
って書いちゃうところ、Verilog に書き換えるときには
for(i=0;i!=10;i++)
と似たような機能に書き換えているんですが、これくらいのことは HLS が自動でやってくれるのかな?

by tom01h | 2018-12-28 20:42 | Trackback | Comments(0)

tiny-dnn アクセラレータの pooling が遅い

tiny-dnn アクセラレータが Ultra96 でまともに動くようになったので、CORA にも変更を反映しました。

話は変わって、tiny-dnn を Arm で動かすと Pooling の順伝搬が非常に遅いように見えます。
ソースコード を眺めてみると、カーネル毎のデータにアクセスするためにデータ配列の Index の配列を作って、何度もメモリを読みながらデータアクセスをしている模様。
Intel の場合はこのほうが速いのですかね?

by tom01h | 2018-12-21 22:40 | Trackback | Comments(0)

tiny-dnn アクセラレータを Ultra96 で動かしたい5

Ultra96 でキャッシュ有りの DMA 転送を使った tiny-dnn アクセラレータは、学習結果の認識精度が安定しない問題に直面しています。
今までも制御回路のバグで転送バッファを読み出し前に書きつぶしていたり、DMA の転送終了判定を間違っていたりしました。
結局は、どちらも DMA のキャッシュコヒーレンシとは関係ないのですが、キャッシュ有で DMA を使った時だけ問題が見えてきます。
今回もキャッシュコヒーレンシを疑いつつ解析を始めたのですが…

手詰まりなので、DMA 単体からキャッシュコヒーレンシのテストを始めました。
DMA 単体だとうまく動いたので、少しづつ tiny-dnn アクセラレータの構成に近づけていこうと RTL を眺めていたらバグ発見。
AXI ストリームマスタが M_AXIS_TREADY のネゲートを受けるタイミングが、転送開始の直前、もしくは終了の直前だと M_AXIS_TVALID のアサート期間が開始前だと1個多く、終了前だと1個少なくなる。
修正してみましたが… 不発。ここじゃない模様。

今までは udmabuf を大きく確保して分割して使っていましたが、用途別に4個の udmabuf を確保してみました。
なんかちょっと良くなった気がするけどまだ…

で、アクセラレータ行きのバッファの1個を O_SYNC 付きで開くと直った。
こいつが犯人みたいです。
さらに試してみると、今まではバッファ1からアクセラレータにDMAしつつ、ユーザメモリからバッファ2にコピーをする場面がありましたが、これを同じ時間に実行しないようにプログラムを変更したら直りました。原因は不明。
f0054075_00120791.png
github 更新しました。

by tom01h | 2018-12-20 23:42 | Trackback | Comments(0)

tiny-dnn アクセラレータを Ultra96 で動かしたい4

キャッシュ付き DMA をいったんあきらめて、キャッシュなしで DMA 転送をしてみました。
こんな感じ で、転送と演算を並列動作しているプログラムは認識率は 97.41% で安定。
並列化していないプログラムは不安定。

プログラムを見比べて思いつく疑惑。

DMA の終了判定を間違っているっぽい。
DMA の転送が終わっていないのに、DMA リセットをかけているのか、IP 側の受け取り状態を解除しているのが原因じゃないかと思う。

よく見る終了判定
while ((dma_addr[0x04/4] & 0x1000)!=0x1000); // Wait for the tx to finish
最初のうちに起きていたハングアップを避けるために今まで使っていた終了判定
while ((dma_addr[0x04/4] & 0x3)==0); // Wait for the tx to finish

よく見る終了判定に変更したら、並列化していないプログラムも 97.41% で安定しました。

シミュレーション結果と一致しないのは、コンパイラのバージョン違いってことにしておきます。

DMA でキャッシュを使う設定(AxCACHE=0xf,AxPROT=0x2,FF41A040=0x3)にしたら…
やはり認識率が一定しません。

この設定で udmabuf を O_SYNC 付きで開くと期待通りの動きです。
やっぱりキャッシュ付き転送になっていないのかな?

残念ながら時間切れ。来週は DMA 単体でテストするかな…

by tom01h | 2018-12-13 23:59 | Trackback | Comments(0)

tiny-dnn アクセラレータを Ultra96 で動かしたい3

tiny-dnn アクセラレータがいまだ Ultra96 上では安定して動きません。
実行時間的にはだいたい期待通りなんだけど、実行結果(認識率)に再現性がないです。
いやなことに、正解だと思っている認識率 96.95% よりも高いことが多いのですが…

Interface の 2019年1月号 の読み返したけど、やり忘れていることはなさそう。
udmabuf の説明 を読んでみると、デバイスツリーに登録して dma-coherent を設定しないといけない気もしますが、試してみたけど変わりません。
DMA の設定の相性問題 で Petalinux ツールがうまく動かないのも疑ってみたけど違うようです。
しかも、いつからか Wifi が使えなくなっています。
DMA のデバイスツリーから dma-coherent を外すと Wifi 復活しました。→ 単に dd の書き損じの可能性もあります。

しかし、Ultra96 は何をやるにも時間がかかります。
だいたいの原因は、ルートファイルシステムが 1.5GB もある事かと…
しかも、Petalinux ツールはルートファイルシステムのコピーを何種類も作って、あっちで作ってこっちにコピーとかもしています。
あと、dd もすごく時間かかるし、たまにうまく書けていないこともある感じです。
ちなみに、VirtualBox が PC 内蔵の SD カードリーダを認識してくれないので、古い USB カードリーダを持ち出しています。
それが原因で dd が遅いのもあると思います。
また、形が悪くて隣りのポートもつぶしたりするので USB カードリーダを買ったのですがまだ届きません。
ついでに、机のわきに固定する形の USB ハブ を買いました。
f0054075_20030769.jpg
悪いのは DMA の使い方じゃないのかなぁ?
CORA はちゃんと動いているみたいだけど…

by tom01h | 2018-12-11 23:46 | Trackback | Comments(0)

tiny-dnn アクセラレータを Ultra96 で動かしたい2

前回は reserved-memory で Linuz が使わないようにした領域を DMA バッファに使おうと思って上手く出来ませんでした。
udmabuf の使い方もわかったところで、再度 Ultra96 上での実行に挑戦してみます。

結論。速くなったけど、結果に再現性がない。まだ上手く行っていないところあるのかなぁ?
ちなみに認識率はちゃんと動いていると思われる時よりも高くなります。
[覚悟を決めて Verilator で 20000 サンプルの学習をしてみました。96.95% でした。ちなみに 10分ちょっとかかりました。]
f0054075_20231846.png
まだなんか怪しいけど、github に置きました。グラフの上の方を見たければそちらをどうぞ。

Ultra96 への移植では Interface 2019年1月号 がとっても参考になりました。
もう一度読み返して、怪しい動作の解析をしたいと思います。

そうは言っても、記事で気になるところを…
汎用 GEMM アクセラレータを作るのが目的ならこの記事で良いのかなと思います。
が、畳み込みを高速化したいのなら、CPU で im2col をやったらダメかと思います。
転送速度がネックだとわかっていつつ、ほぼ 9倍(3x3conv)にデータを増やしてから転送するなんて…
いや、他がすごく良かったのでここが気になるって話です。
あと、HLS 使ったら仕方ないのか?って気もしますが、ユーザメモリから DMA バッファへの同じデータの転送を何度もやらない工夫をしているみたいですが、何度も同じデータを DMA 転送しているのも気になります。
さらに、IP の中もダブルバッファ化するとか HLS でも出来るのですかね?
出来ないなら、HLS もまだまだって気もします。

by tom01h | 2018-12-09 21:18 | Trackback | Comments(0)

tiny-dnn アクセラレータのバグ取りの日

tiny-dnn アクセラレータの動きが不審なので、落ち着いて解析してみます。

まずは認識率に再現性がなくなったところから。
tiny-dnn は学習過程でランダムを使っていないみたいで、毎回同じ認識率を出していました。
ところが最近、いつからか分からないけど、認識率に再現性がなくなっていました。
原因はおそらく DMA バッファ(アクセラレータ→ユーザ空間)の上書きです。
DMA バッファからユーザ空間への転送を演算と並列処理できるようにしたことで、演算がとっても短いときにデータの転送が終わる前に次のデータで上書きされていたのかと思います。
DMA バッファをダブルバッファにしたことで、認識率が 96.95% で落ち着くようになりました。
97% 割ってしまったのは悔しいですが…
というか、再現しないときの方が認識率が高いって…

次は傾きの逆伝搬がとっても遅い原因を探ります。
CPU で流している限りは順伝搬と同じくらいの計算量に見えています。
だから、アクセラレータを使っても同じくらいの時間で終わるはずと思ったのですが…
このアクセラレータは出力の深さだけ並列実行できるのですが、逆伝搬では入出力が逆転して入力の深さだけ並列実行するようになります。
そして、入力層の深さは 1ですから、入力の傾きを求める計算では並列実行できません。
バグで遅いのかと思っていたけど違って、このアクセラレータの弱点っぽいです。
がしかし、入力の傾きって必要ないですよね?
少しずるいけど、取っちゃいました。
[Corei5 の値が間違っていたので差し替えました。あと、目標が高すぎるとくじけるので、Celeron 追加しました。]
f0054075_15482969.png
あともう一個。
こっちはまだ直してないけど、乗算器のステージングが1ステージ少なかった。
BRAM から読んだデータを、そのサイクルで乗算器が使っている模様…

by tom01h | 2018-12-08 22:40 | Trackback | Comments(0)

tiny-dnn アクセラレータで udmabuf を使う

tiny-dnn アクセラレータの動きが怪しいので udmabuf を使ってみたいと思います。

その前に、バイアスの傾き計算を少し変更しました。
出力の傾きを DMA バッファにコピーするときに、同時にバイアスの傾きを計算することでデータアクセス回数を削減する狙いです。
計算量は少ないので CPU で計算させています。
速くはなりましたが、期待していたほどの効果はありませんでした。
逆伝搬はどこに時間がかかっているのか解析が必要みたいです。

で、udmabuf の話に戻ります。
ドライバ開発の手順はやはり、ここ を参考に進めます。
udmabuf のページのサンプルコードの文字列がなぜか unsigend char* でコンパイルできずにはまりましたが、それ以外は2つのリンク先の通りにやると出来ました。
具体的なことは明日 github に書けることを期待して…

ついでに非キャッシュで DMA をするとどうなるか試してみました。
パイプライン化の効果があったか、パラメタの傾き計算以外はあまり変わりません。
(昨日の絵でオレンジと青が遅くなろうが変わらないってこと。)
パラメタの傾き計算では、すでにテータ転送がネックになるのでしょうか?

あと、遅いのはパラメタの傾き計算じゃなくて、傾きの逆伝搬でした。
条件の違うデータがいろいろと混ざっていますが…
f0054075_00292352.png
続きは明日やろう…

by tom01h | 2018-12-07 23:59 | Trackback | Comments(0)

tiny-dnn アクセラレータをパイプライン処理する1

先日は tiny-dnn アクセラレータの処理時間を (順方向だけだが) 大雑把に見積もってみました。
CORA では鉛筆なめた数字に結構近い結果が出ているみたいです。

ついでなので、データ転送と演算の並列処理化を進めたいと思います。
第1段ではユーザメモリと DMA バッファ間の転送とそれ以外を並列処理します。
こんな感じ。
f0054075_20013073.png
大雑把な見積もりでは 7.09秒かかる処理が、CORA では実際には 7.8秒かかっています。

ちなみにこの変更で認識率が上がったのですが、その値が Ultra96 での認識率と一致しています(誤報?)。
Ultra96 はまだちゃんと動いていないのでこっちがおかしいのかと思っていたのですが、おかしいのは今までの CORA の環境なんですかね?

もう少しいじっていたらさらに認識率が上がりました… わけわかんない…
いや、再現性が無いぞ。

by tom01h | 2018-12-06 23:14 | Trackback | Comments(0)