XILINXのDSP推論
普段RTLで演算を書くときは、合成器の推論に任せっぱなしだったのですが、前回の延長で、4サイクルでバイリニアの積和を考えている途中で、ちょっと気になることがあって、少し実験をしてみました。
実際、多くのケースでDSP48E1をかなりうまく推論してくれるようですが、どうもアキミュレータへの足し込みが入ると推論をミスするケースがあるように思えます。
RTLで書いたり、DSP48E1プリミティブを直接呼んだりで実験したところ
DSP48E1プリミティブを直接呼ぶと
と、当然DSP1こになるところ、OPMODEに関連する部分を使う等価RTLを書いてみると
と、積和部分がCLBを使ったロジックで構成されてしまうようです(書き方が悪いのかもしれませんが)。
もちろん ADDMACC_MACRO とか MACC_MACRO とかを使えば解決できるわけですが、この辺のマクロは内部パイプラインがブラックボックスになっており、イマイチ面白みがありません。
そこで DSP48E1プリミティブを直接呼ぶ事も踏まえていろいろ考えてみました。
ついでにこのあたりでいろいろ気が付き始めたのですが、GPU等でよく使う行列演算の中で、4x4 とか 3x3の行列演算が多数あって
a*x + b*y + c*z + d
的な計算をするわけですが、固定小数点に限定すれば DSP48E1 の PCOUT と PCIN をうまく繋いでカスケードすれば、殆ど CLB を消費せずに書けることに気が付きました。
ひとつだけ厄介な問題があって、DSPをカスケードして後段の加算器を乗算器とセットで効率よく使うには、乗算のステージをDSP毎にずらしてやる必要があるようです。
で、この辺は UG479の付録Aとか読んでいただければ想像つくかと思います。
で、a*x + b*y + c*z + d な演算をDSP48E1を直接呼んで、5段パイプラインの演算を書いてみると、非常にコンパクトで高速なモジュールが出来ました。
で、同じ動きをする演算をちゃんと乗算ステージをずらしながらRTLで書き直してみると、まったく同じネットリストが出てきました。ISEやVivadoの推論なかなか大したものです。
汎用性をひとまず置いておくと、DSPへのマッピングを狙ったコードを書くのは結構有効な気がします。
ちなみに DSP48 の乗算器は 18x25 です。単精度浮動小数点の仮数部は暗黙の1と符号を入れると25bitです。
GPUだとしばしば、座標値(整数)×浮動小数点という演算が発生しますが、座標値はバイリニアなどのためのサブピクセル入れても18bitに十分収まるるはずです。
DSPの構造を意識して書けばかなり効率的な書きかたが出来そうな気もします(もっと言えば、そもそも仮数部も18bitで足りる気もします)。
DSPの乗算器と加算器を有効に使うには、乗算結果をそのまま次のステージで加算に使う必要があります。
なので48bitあるDSPのPレジスタを活用しながら、内部でなるべく固定小数点のまま演算を進めて、除算などの必要のあるステージでだけ正規化して必要精度のbitだけ取り出し直すということをやれば、いい感じにFPGAにマッピングできそうな気がします。
« テクスチャキャッシュを試作してみました | トップページ | 除算の検討(回復法と非回復法) »
「FPGA」カテゴリの記事
- LUT-Networkの蒸留とMobileNet風構成とセマンティックセグメンテーション(2020.03.09)
- LUT-Networkの蒸留(Distillation)について(2019.12.29)
- FPGAでのDNN(Deep Neural Network)の整理(LUT-Netまとめ)(2019.12.15)
- LUT-NetのFPGAリソースについて(2019.12.08)
- MNIST認識のリアルタイム動作環境更新(2019.09.02)
この記事へのコメントは終了しました。
コメント