雑多な趣味の記録帳

tom01h.exblog.jp

タグ:ニューラルネット ( 85 ) タグの人気記事

SystemC で配列インデックス生成 (逆方向)

畳み込み用の配列インデックス生成回路を SystemC 記述に変更中です。
昨日は順方向伝搬に対応したので、今日は逆方向伝搬に対応します。

逆伝搬ではいろいろ工夫をした記憶があるのですが、もはやその工夫を覚えていません。
しかも、Verilog のソースを見てもわかりにくい…
でも、C++ で書いたソースを git が覚えていてくれました。
これ の 200 ~ 230 行あたりがそれです。

github に登録しました。
先のソースと若干違うのは、ウェイトを読み込む際にデータ順を入れ替えているためです。

なんだか、シミュレーション時間がどんどん遅くなっていきます…

by tom01h | 2019-03-23 19:16 | Trackback | Comments(0)

SystemC で配列インデックス生成 (順方向だけ)

畳み込み用の配列インデックス生成回路を SystemC で記述しようとしています。
SystemC を使うための調査と準備もだいたい終わったので、そろそろ SystemC を使った設計を始めようと思います。

まずは、分かりやすい順方向だけを SystemC 対応します。
逆方向とウェイトの傾きの計算は、一旦 CPU での計算に逆戻りです。
何とかシミュレーションは動くようになったので github に登録しました。
とりあえず VivadoHLS を使って Verilog の生成は出来ているようですが、生成した Verilog でのシミュレーションはまだ確認していません。

将来的にダブルバッファにして、転送と演算をパイプライン動作させることまで視野に入れています。
そのために、SystemC の部分は 4つのスレッドに分割しています。
よく考えてみると、入力データの配列インデックス生成部分以外は Verilog 記述のままの方が良かったかもしれません。
パイプライン化の時に、もっとちゃんと考えてみたいと思います。

Verilog で書いていた時よりも素直な記述にしたのと、ほとんど機能の多重化がなくなっているのもあわせて、SystemC 化でかなり読みやすくなったと思います。
まぁ、逆方向とかに対応するとまた、読みづらくなるかもしれませんが…


by tom01h | 2019-03-22 16:33 | 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)