この記事について
先日、Design Solution Forum 2018に行ってきました。僕自身は、FPGAは今年に入ってから独学で始めたばかりで、本業も異なる領域なのですが、色々と面白いお話を聞くことが出来ました。
NECの方が講演の中で、非常に有益な高位合成(HLS)用のノウハウを共有してくれました。この場を借りてお礼申し上げます。
発表資料が公開されていないので、覚えている範囲で本記事にまとめようと思います。
お願い
本記事の内容は、僕が講演を聞いた中で覚えている内容を記すものです。そのため、間違えがあった場合には、その責任は全て本記事を書いた僕にあります。
もしも間違え、追加がありましたら教えていただけると幸いです。
Tips
-
Deep Learningの実装に関して
- GPU用の実装とFPGA用の実装では、実装方針が異なる
- ネットなどに転がっているDeep LeaningやCNNのサンプルコードはGPU用である場合が多いので、そのままFPGA(HLS)で実装しても性能でない or リソース不足になる
- GPU用コード: データを大きな行列/ベクトル単位で扱い、並列処理で一気に計算。メモリアクセスが多い
- FPGA用コード: プロセスレベルでのパイプライン化。各層ごとにハードウェア化して、各層がラインバッファを持つようにする。結果、DRAMアクセスではなくFIFO等へのアクセスにできる。また、下手に実装を工夫するよりも、素直にfor文で畳み込み演算を書いた方が速い
- 注: ここでいう「プロセスレベル」とは、CONVOLUTIONの1層目、CONVOLUTIONの2層目、MAX POOLING、とかの単位だったと思います。「海外勢と日本で言い方が違うんですよね」みたいなことを言っていた気がします。とにかく、演算子レベルで並列化やパイプライン化するよりも、少し大きなプロセスレベルでパイプライン化して、処理単位をラインにして、ラインバッファを使う方が有利、というのが言いたいことだと思います。
-
動作周波数を増やすと回路規模は大きくなる
- タイミング制約を満たせないときは、開始間隔(II)を1ではなく、2とか3に増やすと解決するかも
-
GPUコードはIF文苦手
-
FPGAはIF文得意。ただのセレクタで実現できるため
- そのため、for文の中での打ち切り処理に使うことで高速化ができる
- 例えば、物体検知処理で、あり得ないくらいスコアが低くなったら途中であきらめるなど
for(loop) { ...処理... if (score < threshold) break; ...処理... }
- 個人的追記: IF文を活用した方がいいとはいえ、ネストしたり複雑になるとハードウェア増加するのでNGだと思う
-
FPGA内において、DSP、BRAMは物理的な配置場所があらかじめ決まっている。結果、最後の配置配線でタイミング制約を満たせないことが多々ある。
- DSP、BRAMの前後にレジスタを入れることで解決できるかも
-
ある関数をたくさん使用しているとき、それを高速化のために単にINLINE化してしまうと、その分だけハードウェアが作られてしまい、回路が大きくなってしまう。また、配線も複雑になる。
- 関数を演算子化して、それを使うようにする