Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Polyphony の並列化

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 42 Anzeige

Polyphony の並列化

Herunterladen, um offline zu lesen

Polyphony の並列化についての社内で作った資料。一番言いたいことはちゃんと考えてパイプライン化したプログラムじゃないと高位合成しても高速化できないということ。

Polyphony の並列化についての社内で作った資料。一番言いたいことはちゃんと考えてパイプライン化したプログラムじゃないと高位合成しても高速化できないということ。

Anzeige
Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Andere mochten auch (20)

Anzeige

Ähnlich wie Polyphony の並列化 (20)

Anzeige

Aktuellste (20)

Polyphony の並列化

  1. 1. Polyphony の並列化 有限会社シンビー
  2. 2. Polyphonyはこんなツール 特徴 ● Pythonで書いたコードをHDL(Verilog)に 変換するためのコンパイラ ● オープンソース 得意なこと ● 動くものを早く作る 苦手なこと ● クロックレベルの記述(<=今後の改善点)
  3. 3. Polyphonyの紹介: Q: Can Polyphony accept any Python code? A: No, Polyphony accepts only restricted Python code. Python Polyphony (is a subset of Python) Function Class List(Fixed size) Tuple For/While If/Else ... String Dictionary Set Builtin funcs ... Python のすべてをカバーしているわけではない
  4. 4. Polyphonyのデザイン・フロー:
  5. 5. コンパイラは何をやっているのか? def AND(x1, x2): w1, w2, theta = 2, 2, 3 tmp = x1*w1 + x2*w2 if tmp <= theta: return 0 elif tmp > theta: return 1 実際に「ゼロから作るDeep Learning: Pythonで学ぶディープラーニングの理論と実装」を 読みながらPolyphonyで合成してみた例。
  6. 6. コンパイラは何をやっているのか? tmp = x1*w1 + x2*w2 pp_temp0 = x1*w1 pp_temp1 = x2*w2 tmp = pp_temp0 + pp_temp1 処理を分解 IR と SSA
  7. 7. コンパイラは何をやっているのか? tmp = x1*w1 + x2*w2 pp_temp0 = x1*w1 pp_temp1 = x2*w2 tmp = pp_temp0 + pp_temp1 pp_temp0 = x1*w1 pp_temp1 = x2*w2 tmp = pp_temp0 + pp_temp1
  8. 8. コンパイラは何をやっているのか? tmp = x1*w1 + x2*w2 pp_temp0 = x1*w1 pp_temp1 = x2*w2 tmp = pp_temp0 + pp_temp1 pp_temp0 = x1*w1 pp_temp1 = x2*w2 tmp = pp_temp0 + pp_temp1 スケジューリング (一種の並列化)
  9. 9. 使用方法による分類 • TypeI : Function-Call-Like Usage <関数呼び出し> タイプ • TypeII : Thread-Like Usage <スレッド> タイプ • TypeIII : Stream-Processing Usage • ソフトウェアからみた分類
  10. 10. <関数呼び出し> タイプ • バリエーション – 非同期(ソフト的な) – 突き放し • 例 – TCP/IP の CRC 計算 Int main() { …. …. rv = offload(arg0, arg1, arg2); …. …. } FPGA arg0 arg1 arg2 rv
  11. 11. Polyphony は関数も最適化する if illegal_op == False: tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_store self.store(tmp_store_addr, tmp_store_value) 関数予備出し
  12. 12. Polyphony の逐次処理の進化 • 最初の実装 – 単純な逐次処理をスケジューリング – 関数コールもステージ • 改善された実装 – 関数コールをインライン展開 – 元の関数呼び出しと離れてスケジューリング – 可能な限り最適化 • 追加機能 – オブジェクト指向(class)に対応 – インスタンス作成をインライン展開 – ライブラリ化可能 • for 文の展開(アンロール) • for文のパイプライン • 特定条件のパイプライン 今後の課題
  13. 13. スケジュール/最適化してもさほど高速化しない if illegal_op == False: tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_store self.store(tmp_store_addr, tmp_store_value) 関数予備出し スケジュール 最適化
  14. 14. Polyphony での高速化は? スケジューリング (一種の並列化) パイプライン化 逐次処理の順序を 保ちながら並列化 • for分のパイプライン • worker による実現
  15. 15. OpenCV を高位合成でコンパイルして 高速ハードを作れますか? スケジューリング (一種の並列化) パイプライン化 逐次処理の順序を 保ちながら並列化 この部分をうまく ハードに落とせない と高速化できません
  16. 16. 例えばステレオからの視差を得る D
  17. 17. OpenCV のライブラリ • StereoBM – ブロックマッチング • StereoSGBM – セミ・グローバル(ブロック?)・マッチング これらのソースを高位合成でコ ンパイルできるだろうか?
  18. 18. OpenCV のソースを見る parallel_for: 高速化のためのソフトウェア的な様々な工夫 高位合成のコンパイラに通すことが困難な場合が多い
  19. 19. StereoBM(ブロックマッチング) ブロックの比較
  20. 20. StereBM(ブロックマッチング) ラインバッファを使って 比較ができる OpenCV とは離れて、原理を追うことで FPGAで実現する道筋が立てやすいアルゴリズム 高位合成で実現可能性が高い
  21. 21. StereoSGBM(セミ・グローバル・マッチング) パスr パスr に沿って積算していく。 単純なブロックマッチングではない。
  22. 22. StereoSGBM(セミ・グローバル・マッチング) 複雑なアルゴリズム 高位合成で実現してほしいが パイプライン化が難しい ラインバッファを使っ て比較ができる リアルタイム処理が困難 パイプラインが破たん 捜査も逆向き すごく工夫が必要 パイプライが 破たん 工夫が必要
  23. 23. ニュース!!SGMを提供!! この難しい処理を HDL 化に成功!! 視差画像を 抜き出し!!
  24. 24. 高速化したいならパイプラインを意識 したプログラムが必要 スケジューリング (一種の並列化) パイプライン化 逐次処理の順序を 保ちながら並列化 この部分をうまく ハードに落とせない と高速化できません
  25. 25. 使用方法による分類(再掲) • TypeI : Function-Call-Like Usage <関数呼び出し> タイプ • TypeII : Thread-Like Usage <スレッド> タイプ • TypeIII : Stream-Processing Usage
  26. 26. 並列化の種類による分類 • TypeI : Scheduling スケジューリングによる並列化 • TypeII : Pipeline パイプラインによる並列化(密結合) • TypeIII : Pipeline パイプラインによる並列化(疎結合)
  27. 27. 逐次処理をスケジューリングする if illegal_op == False: tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_store self.store(tmp_store_addr, tmp_store_value) スケジュール 最適化
  28. 28. スケジューリングされた処理は リソースを共有している FF FF リソース 再入不可(ソフトウェアの用語をつかうと)
  29. 29. HDL の排他制御 VHDL Verilog-HDL process (clk) begin .... .... ff0 <= ‘0’; .... .... end process; always@(posedge clk) begin .... .... ff0 <= 1b‘0; .... .... end 書き込みはあるブロック内と制限される。 • VHDL のブロック: process • Verilog –HDL のブロック: always
  30. 30. HDL の排他制御 Process FF Process 書き込みは1か所からのみ
  31. 31. ステージを分けてFF を排他制御 FFなので排他制御が必要 各ステージは1clock CPU設計例
  32. 32. リソースの書き込みを排他。 FF で情報を持ちまわる FF FF 再入可能 FF FFなので排他制御が必要だが 参照は自由(密結合)
  33. 33. 再入可能にしてパイプライン化 FETCH EXECUTE MEMORY WRITE FETCH EXECUTE MEMORY WRITE FETCH EXECUTE MEMORY WRITE FETCH EXECUTE MEMORY WRITE FETCH EXECUTE MEMORY WRITE
  34. 34. 疎結合のパイプラインの例 (AXI-Stream) 各モジュールは独立しており 必要な情報はすべて流さないといけない 他のモジュール内の情報の参照ができない(疎結合) 今後は MPI とか OpenMP を研究予定
  35. 35. おまけ: for 文 • for 文 + 配列は、スケジューリングの中でうま く対応すればパイプライン化が見込めやすい 比較的まれな例(だとおもう) – でも配列の参照方法や順序などをチェックしない といけないので大変 – そう意味では foreach 文は、コンパイラにとってシ リアライズが確定するので大変助かる構文
  36. 36. まわりくどくなりましたが それを踏まえて Polyphony の新機能の紹介
  37. 37. Polyphony:並列プログラミング 並列計算モデルを構築するための道具を用意 ●Module ●Worker ●Port
  38. 38. 並列プログラミング Module ●回路全体またはその一部を表す単位 ●外部入出力のためのPortを持つ ●さまざま処理を独立して行う複数のWorker を持つ
  39. 39. 並列プログラミング Worker ●Moduleに含まれる並列動作する処理の単位 ●入出力のためのPortを持つ ●Workerの持つPortは外部もしくは内部(別の Worker)と接続
  40. 40. 並列プログラミング Port ●データのやり取りを行うためのチャネル ●ModuleおよびWorkerの入出力になる ●単一データ用のPortとFIFOとして動作する Queueがある
  41. 41. 並列プログラミング 例: @module # デコレータによりクラスをModuleとして指定 class Blink: def __init__(self, interval1, interval2): self.led1 = Port(bit, 'out') # 出力ポート self.led2 = Port(bit, 'out') # 出力ポート self.append_worker(self.main, self.led1, interval1) # Workerの登録 self.append_worker(self.main, self.led2, interval2) # Workerの登録 # Workerの定義 def main(self, led_port, interval): led:bit = 1 while is_worker_running(): led_port.wr(led) # ポートへの書き込み led = ~led self._wait(interval)
  42. 42. おしまい Github https://github.com/ktok07b6/polyphony

Hinweis der Redaktion

  • Polyphony がどんなツールなのかをかいつまんで再度まとめると
    Python で書いたコードを HDL に変換するコンパイラ
    動くものを早く作る
    性能には“現在のところ”重きを置いていない
    というツールになります。
  • そして、
    Python のコードをコンパイルすると言ってもすべてのコードをコンパイルできるわけではなく、
    とうぜん、pritnt などの文字列などはサポートされておらず、Python のサブセットになっています。
  • デザインフローとしては
    「Python によるコードの記述」をし
    ここが重要なのですが「Python によるコードの実行」によりデバッグをしておきます そして、「Polyphony によりコンパイル」をし 生成された Verilog コードを「シミュレーション」し 各ベンダーのツールで「合成」をしたのち
    実機で「実行」するという形をとります。
  • でその Polyphony というコンパイラは何をしているかというと
    上のような 掛け算と足し算の組み合わせを例にとります。
  • 内部的には IR という内部表現にして、代入も必ず一回という SSA 形式にします。
    こうするとコンパイラ内で最適化を掛けやすくなります。
  • これらの文章の順序性をみます。
  • これらはスケジューリングと呼ばれたりします。
    並列化の一種です。
  • RISC-V の実装に先立ち使用法による分類をしました。
    これは多分にソフトウェアから見た分類であり、また、Zynq に代表される、 昨今の SoC と FPGA の融合された環境をかなり意識した分類になっています。
    また、学術的なエビデンスが必要である場合、オープンソースのサイトから 抜き出してカウントしたなどの調査が必要かと思いますが、 ここではそのような正統的なアカデミックなアプローチをとっているわけではありません。
    ということをお断りしたうえで使用法の分類をいたします。
  • 関数呼び出しタイプと分類したものは、FPGA のそばに CPU がありそこから関数のような形で呼ばれることを念頭に置いた分類です。
  • さらに LS/SW に代表されるメモリへのアクセスも処理を遅くします。実装としては関数を呼んでいるわけですが、その関数の先で何クロックも消費します。
  • ここで、Polyphony のこの数年の逐次処理に対するコンパイルのアプローチの変遷を語りたいと思います。
    最初の実装は、単純な逐次処理のスケジューリングでした。関数コールもひとつのクロックを要するステージが必要でした。
    次に、関数コールをインライン化できるようになりました。これで関数コールの先も一緒に最適化できるようになりました。
    その後、追加機能として、オブジェクト指向に対応し、それらのインスタンスをもインライン展開するようになりました。
    そられのインスタンスはライブラリ化可能なので実績のあるクラスを他で流用できるようになりました。
    現在、取り組んでいるのは for 文のパイプライン化やアンロールであったり、特定条件化のパイプライン化です。
  • 先ほどの話に戻ると、 LS/SW に代表されるメモリへのアクセスはそもそも処理を遅くするのですが、
    関数を呼ぶぶことでその関数の先で何クロックも消費します。
    最近の Polyphony はちょっと賢くなって関数呼び出しをインライン化して最適化します。
    しかし、これは先ほども言いましたが、あくまでスケジューリングです。
    パイプライン化しているわけではないので、微々たるスピードアップをしますが、
    CPU としての高速化はしません。
  • さきほどの高位合成の高速化で スケジューリングとパイプライン
    という話をしました。Polyphony では 普通に書いたプログラムを逐次処理をスケジューリングし並列化します。
    そして、意図的にworker でパイプライン化したプログラムを並列化します。
  • でここで、高位合成をしたいといったときの端的な質問になるのですが、
    私は画像処理をしたいと思っています。
    「OpenCV を高位合成でコンパイルして高速ハードを作れますか?」
    という質問に対しては、あまりいい回答が出来ないのが現状です。これは Python でなくても C 言語でもそうだと思います。 現状のソースのパイプライン化についてうまい回答がないからです。
  • たとえば OpenCV にあるステレオ視差のライブラリを考えます。
  • 2つの種類があるのですが、BM と SGBM というもので
    これらを高位合成でコンパイルできるか?ということです。
  • OpenCV のソースを見ると parallel_for とソフト的な様々な工夫をしていることがわかりませう。
    これは高位合成のコンパイラにとってかなりつらい工夫です。 この工夫がかえってコンパイルできない原因になってしまいます。
  • 別の要因もあります。
    例えばブロックマッチングはブロックの比較です。
  • 原理的にはラインバッファを使って比較ができます。 なので、FPGA 向きと言えます。
  • ところが、SGBM というのがあるのですが、これはブロックマッチングではなく 経路に沿って積算することで正しいし視差を求めるアルゴリズムになっています。
  • 経路によってはラインバッファで対応できますが、 パイプラインが破たんする箇所や工夫しないとできない部分、 そもそもリアルタイム処理できない部分があり
    リアルタイム処理するなら FPGA 向きではないアルゴリズムになっています。
    しかし、こういう複雑なアルゴリムこそ高位合成で実現してほしい。
    現状は、この手のソースは既存のソースをコンパイルしただけでは高位合成では実現できません。 その高位合成のルールに従って書き直す必要があるのですが、それであれば Verilog で書いた方がよっぽど早く実現できます。
  • ここで自社のCMをさせていただきます。
    先ほどの難しい SGM を数式を元に HDL 化しました。視差画像の抜き出しが出来ます。 ご興味のある方は InterBEE で発表予定ですので、来ていただければと思います。
  • でここで、高位合成をしたいといったときの端的な質問になるのですが、
    私は画像処理をしたいと思っています。
    「OpenCV を高位合成でコンパイルして高速ハードを作れますか?」
    という質問に対しては、あまりいい回答が出来ないのが現状です。これは Python でなくても C 言語でもそうだと思います。 現状のソースのパイプライン化についてうまい回答がないからです。
  • RISC-V の実装に先立ち使用法による分類をしました。
    これは多分にソフトウェアから見た分類であり、また、Zynq に代表される、 昨今の SoC と FPGA の融合された環境をかなり意識した分類になっています。
    また、学術的なエビデンスが必要である場合、オープンソースのサイトから 抜き出してカウントしたなどの調査が必要かと思いますが、 ここではそのような正統的なアカデミックなアプローチをとっているわけではありません。
    ということをお断りしたうえで使用法の分類をいたします。
  • RISC-V の実装に先立ち使用法による分類をしました。
    これは多分にソフトウェアから見た分類であり、また、Zynq に代表される、 昨今の SoC と FPGA の融合された環境をかなり意識した分類になっています。
    また、学術的なエビデンスが必要である場合、オープンソースのサイトから 抜き出してカウントしたなどの調査が必要かと思いますが、 ここではそのような正統的なアカデミックなアプローチをとっているわけではありません。
    ということをお断りしたうえで使用法の分類をいたします。
  • 先ほどの話に戻ると、 LS/SW に代表されるメモリへのアクセスはそもそも処理を遅くするのですが、
    関数を呼ぶぶことでその関数の先で何クロックも消費します。
    最近の Polyphony はちょっと賢くなって関数呼び出しをインライン化して最適化します。
    しかし、これは先ほども言いましたが、あくまでスケジューリングです。
    パイプライン化しているわけではないので、微々たるスピードアップをしますが、
    CPU としての高速化はしません。
  • HDL の基本的なことになり、スペシャリストの方も多い場で、恐縮ですが、 HDLでは排他制御、ソフト的な用語かもしれませんが、があります。
    つまりあるブロック内でのみ書き込みがゆるされるということです。
  • 書き込みは基本的に1っ所からです。参照はいくらでもできるのですが
    FF という性質上1つのとこからしか書き込めないわけです。
  • さきほどの CPU のステージを私なりに簡略化した絵がこれです。 PC や Registers はどこかに所属して、書き込みが整理されるわけです。
    もちろん、一か所に集約して、全部から書き込みできるようにも設計できるとは思いますが
    そうすると、書き込み処理は混乱すると思います。
    ここではオーソドックスと思われるはじめてCPUを作る人が考えやすい形式を想定します。

×