学位研究 第14号 イギリス高等教育の学位統一への動き —高 …...2008/08/29 · 学位研究 第14号 平成13年3月(論文) [大学評価・学位授与機構研究紀要]
高位合成でDeep learning
-
Upload
mori-labo -
Category
Engineering
-
view
655 -
download
1
Transcript of 高位合成でDeep learning
自己紹介
Twitter● @morittyo
HP● morilab報告書 http://morilab-report.blog.jp/
仕事● RTL設計・検証
○ Verilog , SystemVerilog, VivadoHLS(高位合成)○ 検証メソドロジ(UVM)、ランダム検証、アサーション等
まずはDeepLearningのお勉強
初めはネットだけで頑張っていた
…が、断片的な情報ばかりを収集してしまい全体像がわからなくなってしまった
本を買いました。
⇒3割ぐらい理解した気になった。色々間違ってそう。
ニューロンモデル
複数から入力を受け付ける
● 出力は1つ
Step1 : 各入力を重みと積和演算する
u = weight * x + bias
Step2 : 活性化関数を通す
y = func(u)
*W2
*W1
*W3
x1
x2
x3
∑ func() y
bias
(単純)パーセプトロン
同一層にあるニューロン同士はネットワー
クが存在しない
入力は前段の層からのみ、出力は後段
の層へのみ伝搬する
同一層
・並列実行って感じがするしRTL(FPGA)向きでは?・高位合成を使えば簡単に違いない!(フラグ)
畳み込みニューラルネット(MAXプーリング処理)
2x2エリアの中で最大値を採用する
→画像サイズがWidth,Heightどちらも半分になる
データを適度に間引きつつ、入力画像の位置ずれにもそれなりに効果があるものらしい
ディープラーニング
● 単層のニューラルネットワークは、限定的な問題しか解けない(線形分離)
● 多層のニューラルネットワークは、複雑な問題が解けそうだけどパラメータが複雑
すぎて学習が全然進まない
ディープラーニングは、多層のニューラルネットワークのパラメータをイイ感じに学習する
ことができるアルゴリズムのこと(らしいですよ)
MNISTクラス
MNISTデータセットを読み出すだけのクラス
● http://yann.lecun.com/exdb/mnist/
以下のイメージファイルとラベルファイルに対応
● TRAINING SET LABEL FILE (train-labels-idx1-ubyte)
● TRAINING SET IMAGE FILE (train-images-idx3-ubyte)
高位合成はされないが、テスト時に使用
MNISTデータセット
MNISTデータセットとは?
● 28x28=784画素からなる8ビット(255諧調)モノクロ画像
● 0~9の手書き文字
● 答え(ラベル)付き
● 機械学習業界では有名なデータ(らしい)
● イケてる機械学習だと正解率99%以上とか
実際の背景色は0x00(黒)
convolution_perceptronクラス
畳み込みニューラルネットのモデル
入力層(L1)、中間層(L2)にて使用
● 畳み込み演算○ 入力画像 (幅= IN_X、高さ=IN_Y)○ フィルタウインドウ(幅= CNV_X、高さ=CNV_Y)○ 額縁補正 →外周データは0扱いとし、演算対象と同じ画像サイズで出力
● プーリング演算○ ウインドウ(2x2固定)
○ 最大値選択
● 活性化関数○ ReLU →0以下を0にクリッピングする関数。演算負荷が少なく、学習結果も良いらしい。
softmax_perceptron_fnnクラス
単純パーセプトロンのモデル
→ relu_perceptron_fnnクラスから派生
出力層(L4)で使用
● 活性化関数○ ソフトマックス
■ 出力は正規化され、合計値が常に同じ
■ 活性化関数にてexp関数を使用
なんとなく実装完了
実装にかかった時間はおよそ3日
● C++のテンプレートと仮想関数に嵌るなど
● 学習部分が無いのでとても残念な感じのコード○ 学習後のパラメータを使って動かすことは出来る …
● GitHubに一応コミットしてあります(クソコード)
○ https://github.com/morilab/deep_learning_hls
インターフェース
インターフェース仕様は性能に大きく影響する
● 入力画像○ 28x28x8bit (MNIST)
● パーセプトロン用パラメータ○ Weight○ Filter○ Bias
● 判定結果○ 0~9の各確率
● 学習用パラメータ○ 教師信号(0~9のいずれか)○ 学習率○ その他?(良く分かっていない)
入力画像
● ディープラーニングによる学習を行う場合は大量の画像データを切り替える
● MNISTデータセットを使いたいのでそちらに合わせる
● リードのみ
→今回はサイズがそれほど大きくないのでブロックRAMでの実装を目指す
サイズ : 28x28x8=6272Bit / 784Byte
パーセプトロン用パラメータ● 各パラメータは主に学習時に更新される(リードライト)
● ユーザーは基本的にあまり操作しない○ 初期値の設定→バイアスは0、その他はランダム
○ 学習値の設定→1回設定するのみ
● かなり容量が必要…実用的に動かすには一部外部メモリを使わないと難しい?○ Bias : [L1Size]+([L1Size]*[L2Size])+[L3Size]+[L4Size(10)]○ Filter : [L1Size]*[WindowSize1]+[L1Size]*[L2Size]*[WindowSize2]○ Weight : ([L2Size]*[L2OutFrame(49)])*[L3Size]+[L3Size]*[L4Size(10)]○ →L1Size=32,L2Size=64,L3Size=1024,WindowSize=5x5で見積もると…
Bias=3,114要素,Filter=52,000要素,Weight=3,221,504要素 合計約3.3M要素
サイズの調整が必要 でかい!!
設計仕様
ニューラルネットワーク構成
1層目 2層目 3層目 4層目
セット数 20 20 500 10
フィルタ 5x5 5x5 - -
活性化関数 ReLU ReLU ReLU SoftMax
入力 28x28x8Bit (白黒)
内部変数型 S2.6 (-2.0~1.984375)
出力 各8Bit
とりあえず高位合成してみる
ディレクティブなしの状態
クロック:100MHz(10ns)
ターゲット:xc7z020clg484-1 (ZedBoard)
レイテンシ:約200ms
さすがに200msはシミュレー
ションしたくない…合成は30分弱
デフォルト設定での合成
ディレクティブ(高位合成に対する指示)が何もない場合、
● ループは記述通りに実装されるため、リソースは少ないがレイテンシは大きい
● パイプライン化を行わない
● ループなどの並列実行を行わない
…というふうに、並列化を行わないためレイテンシが(恐らく)最大となる回路を生成
演算処理はProjectSettingにあるクロック周波数を元に適度にFFを挟んだ回路になる
⇒周波数設定を弄るとレイテンシサイクルが減るが、処理の絶対時間は大体同じ
モジュールIFがどうなったか見てみる
項目 I/F セット数 詳細
Input Frame Memory 1 Address[9:0],Data[7:0]
L1 Filter Memory 1 Address[8:0],Data[7:0]
L1 Bias Memory 1 Address[4:0],Data[7:0]
L2 Filter Memory 1 Address[13:0],Data[7:0]
L2 Bias Memory 1 Address[8:0],Data[7:0]
L3 Weight Memory 1 Address[18:0],Data[7:0]
L3 Bias Memory 1 Address[8:0],Data[7:0]
L4 Weight Memory 1 Address[12:0],Data[7:0]
L4 Bias Memory 1 Address[3:0],Data[7:0]
Result Validつき出力
8 Data[7:0]
配列はデフォルトですべて1次元メモリ
(合成結果には接続すべきメモリは含まれない)
● L3_Weightが512kバイト空間をご所望
良し悪しは兎も角、概ね想定通りの結果
1次元メモリなので基本的に異なる要素へのアク
セスができない
(リードだけの場合、2PortRAMの2面読み出しに
なることはある)
レイテンシの内訳を見てみる(全体)
レイテンシ表示は以下のようになっている
[Latency] = [Iteration Latency] × [Trip count]
問題がTrip Count(ループ回数)か、Iteration Latency(1回分の処理にかかるサイクル数)かを考えていく
Loop14が全体レイテンシの約65%を占めてい
る。もう少し細かく見てみることにする。
レイテンシの内訳を見てみる(Loop14)
多重ループになっている
下位レイテンシが上位のいてレーションレイ
テンシになるが、このとき(基本)+2される
⇒多重ループはレイテンシに無駄が出る
ディレクティブを挿入して改善することができる
ループ部分にラベルを追加
ディレクティブの追加にはループにラベルが必要。ログも通し番号でラベルを付けられてしまうため解析が大変
→“<クラス名>_<機能名>_<階層>”という形ですべてのループにラベルを付加した
チューニング、解析いずれにしてもラベルの追加は必須!
ラベル付加後のレイテンシ内訳
ラベルがあると見やすい!
(何故かレイテンシ変わってるけど)
IterationLatencyが大きいところに注目
→下位ループのLatencyを合計した値から大
きく離れている
演算に必要なデータが揃っていないため無駄
に待たされている可能性が高い
→畳み込み演算のFilter/Weightパラメータが
1個づつしか参照できないためでは?
チューニング用に仕様を弄る
1回30分も待つのがつらいので、一時的にサイズを小さくしてみる。
1層目 2層目 3層目 4層目
セット数 20⇒10 20⇒10 500⇒100 10
フィルタ 5x5 5x5 - -
活性化関数 ReLU ReLU ReLU SoftMax
入力 28x28x8Bit (白黒)
内部変数型 S2.6 (-2.0~1.984375)
出力 各8Bit
15分くらいに改善 → チューニング時にとりあえず小さくするのは効果アリ
とりあえずPIPELINEいれてみる
トップ関数にPIPELINEを入れてみる
設定はII(開始間隔)=1にしてみる
→ 目標値なので達成されるかどうかはわからないが、とりあえず入れてみる
VivadoHLSでは良くあること…終わるかどうかも分からないので止める
24時間経っても高位合成終わらず
トップ関数を分離する
全体を一気に高位合成するのは作業効率が悪く現実的ではない
→4層をそれぞれ関数に分離し、個別に高位合成することにする
各層のチューニングが終わったら、その設定をもってトップで高位合成をする。
トップの合成が終わらない場合は、最悪各合成結果をRTLレベルで手で接続する
入出力をバラす
入出力はデフォルトなのでデータ幅=8Bitのメモリになっている
出力は10個バラにする
→HLS_ARRAY_PARTITION complete
その他は32Bit幅のメモリに変更する
→HLS_ARRAY_RESHAPE cyclic factor=4
原因不明の死…blockにすると通る…とりあえずblockで続けることに。。。
Layer4()
weight bias
[31:0] [31:0][7:0]
[7:0]in
[31:0]
Array reshapingさん、突如StackDumpをキメる
ロード系のチューニング
In_L1とParam_L2は同じループ、かつ独立した処理
→ループのマージができる
In_Param_L2は500回繰り返すところなのでパイプライン化を指示
Param_L1をUNROLLで4パラ指示
Layer4チューニング結果
● レイテンシは半分以下になったが、DSPとLUTのリソースは改善の必要あり
● 入出力、パラメータを内部で保持する形になっているのでLayer1~3では別の
チューニングを行う必要がある
成功したこと
● なんとなく高位合成できた○ C++でクラスやテンプレートを使ったコードでも大丈夫だった
○ ディレクティブなしでとりあえず合成できた
● テンプレート使用しても合成できた
○ 一時的に規模を小さくすることで合成時間を短縮できるので、素早いチューニングができる
● 細かいチューニング○ ソースコードは弄らず、ディレクティブのみなら複数の Solutionをプロジェクトで持てる
○ 関数単位でチューニングしていくのが良さそう
○ 良い合成結果を出すためにはソースコードの修正が必要
失敗したこと
● 現実的な合成結果には到達せず○ ディレクティブなしの結果は基本クソ( FPGAの演算に求めるのは並列実行)
○ 畳み込み演算(Layer1,2)は現実的な合成結果にするにはソースコードの根本改善が必要
○ ディレクティブ設定しても落ちたり帰ってこなかったりで大変
● 今回のクラス構造は失敗○ 派生クラスから基底クラスへ細やかなディレクティブ指示ができない(気がする)
● ベタでフラットに関数を並べたようなコードが結局チューニングしやすい○ C/C++で書くけど変に抽象化や汎用化するとチューニングできない
● ポインタをもっと活用しないとダメ○ Layer4のパラメータは内部ブロックで持てる量だったが、 Layer2は絶対無理
○ Layer間のデータ受け渡しが無駄に発生するコードになってしまった
● ディープラーニングできなかった○ もっと勉強します…