Polyphony の並列化

Post on 23-Jan-2018

288 Views

Category:

Software

3 Downloads

Preview:

Click to see full reader

Transcript

Polyphony の並列化

有限会社シンビー

Polyphonyはこんなツール

特徴● Pythonで書いたコードをHDL(Verilog)に変換するためのコンパイラ

●オープンソース

得意なこと

●動くものを早く作る

苦手なこと

●クロックレベルの記述(<=今後の改善点)

Polyphonyの紹介:

Q: Can Polyphony accept any Python code?

A: No, Polyphony accepts only restricted Python code.

Python

Polyphony(is a subset of Python)

FunctionClassList(Fixed size)TupleFor/WhileIf/Else...

StringDictionarySetBuiltin funcs...

Python のすべてをカバーしているわけではない

Polyphonyのデザイン・フロー:

コンパイラは何をやっているのか?

def AND(x1, x2):w1, w2, theta = 2, 2, 3tmp = x1*w1 + x2*w2if tmp <= theta:

return 0elif tmp > theta:

return 1

実際に「ゼロから作るDeep Learning: Pythonで学ぶディープラーニングの理論と実装」を読みながらPolyphonyで合成してみた例。

コンパイラは何をやっているのか?

tmp = x1*w1 + x2*w2

pp_temp0 = x1*w1pp_temp1 = x2*w2tmp = pp_temp0 + pp_temp1

処理を分解IR と SSA

コンパイラは何をやっているのか?

tmp = x1*w1 + x2*w2

pp_temp0 = x1*w1pp_temp1 = x2*w2tmp = pp_temp0 + pp_temp1

pp_temp0 = x1*w1

pp_temp1 = x2*w2

tmp = pp_temp0 + pp_temp1

コンパイラは何をやっているのか?

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

スケジューリング(一種の並列化)

使用方法による分類

• TypeI : Function-Call-Like Usage<関数呼び出し> タイプ

• TypeII : Thread-Like Usage<スレッド> タイプ

• TypeIII : Stream-Processing Usage

• ソフトウェアからみた分類

<関数呼び出し> タイプ

• バリエーション

– 非同期(ソフト的な)

– 突き放し

• 例

– TCP/IP の CRC 計算

Int main(){….….

rv = offload(arg0, arg1, arg2);

….….

}

FPGA

arg0

arg1

arg2

rv

Polyphony は関数も最適化する

if illegal_op == False:tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_storeself.store(tmp_store_addr, tmp_store_value)

関数予備出し

Polyphony の逐次処理の進化

• 最初の実装– 単純な逐次処理をスケジューリング– 関数コールもステージ

• 改善された実装– 関数コールをインライン展開– 元の関数呼び出しと離れてスケジューリング– 可能な限り最適化

• 追加機能– オブジェクト指向(class)に対応– インスタンス作成をインライン展開– ライブラリ化可能 • for 文の展開(アンロール)

• for文のパイプライン• 特定条件のパイプライン

今後の課題

スケジュール/最適化してもさほど高速化しない

if illegal_op == False:tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_storeself.store(tmp_store_addr, tmp_store_value)

関数予備出し

スケジュール

最適化

Polyphony での高速化は?

スケジューリング(一種の並列化)

パイプライン化

逐次処理の順序を保ちながら並列化

• for分のパイプライン• worker による実現

OpenCVを高位合成でコンパイルして高速ハードを作れますか?

スケジューリング(一種の並列化)

パイプライン化

逐次処理の順序を保ちながら並列化

この部分をうまくハードに落とせないと高速化できません

例えばステレオからの視差を得る

D

OpenCVのライブラリ

• StereoBM

–ブロックマッチング

• StereoSGBM

–セミ・グローバル(ブロック?)・マッチング

これらのソースを高位合成でコンパイルできるだろうか?

OpenCVのソースを見る

parallel_for: 高速化のためのソフトウェア的な様々な工夫

高位合成のコンパイラに通すことが困難な場合が多い

StereoBM(ブロックマッチング)

ブロックの比較

StereBM(ブロックマッチング)

ラインバッファを使って比較ができる

OpenCV とは離れて、原理を追うことでFPGAで実現する道筋が立てやすいアルゴリズム高位合成で実現可能性が高い

StereoSGBM(セミ・グローバル・マッチング)

パスr

パスrに沿って積算していく。単純なブロックマッチングではない。

StereoSGBM(セミ・グローバル・マッチング)

複雑なアルゴリズム高位合成で実現してほしいがパイプライン化が難しい

ラインバッファを使って比較ができる

リアルタイム処理が困難

パイプラインが破たん捜査も逆向き

すごく工夫が必要

パイプライが破たん

工夫が必要

ニュース!!SGMを提供!!

この難しい処理を HDL 化に成功!!

視差画像を抜き出し!!

高速化したいならパイプラインを意識したプログラムが必要

スケジューリング(一種の並列化)

パイプライン化

逐次処理の順序を保ちながら並列化

この部分をうまくハードに落とせないと高速化できません

使用方法による分類(再掲)

• TypeI : Function-Call-Like Usage<関数呼び出し> タイプ

• TypeII : Thread-Like Usage<スレッド> タイプ

• TypeIII : Stream-Processing Usage

並列化の種類による分類

• TypeI : Scheduling スケジューリングによる並列化

• TypeII : Pipelineパイプラインによる並列化(密結合)

• TypeIII : Pipelineパイプラインによる並列化(疎結合)

逐次処理をスケジューリングする

if illegal_op == False:tmp_store_addr = self.get_reg_v(rs1) + tmp_add_v_storeself.store(tmp_store_addr, tmp_store_value)

スケジュール

最適化

スケジューリングされた処理はリソースを共有している

FF

FF

リソース

再入不可(ソフトウェアの用語をつかうと)

HDLの排他制御

VHDL Verilog-HDL

process (clk)begin

....

....ff0 <= ‘0’;........

end process;

always@(posedge clk)begin

....

....ff0 <= 1b‘0;........

end

書き込みはあるブロック内と制限される。• VHDL のブロック: process• Verilog –HDL のブロック: always

HDL の排他制御

Process

FF

Process

書き込みは1か所からのみ

ステージを分けてFF を排他制御

FFなので排他制御が必要

各ステージは1clock

CPU設計例

リソースの書き込みを排他。FF で情報を持ちまわる

FF

FF

再入可能

FF

FFなので排他制御が必要だが参照は自由(密結合)

再入可能にしてパイプライン化

FETCH

EXECUTE

MEMORY

WRITE

FETCH

EXECUTE

MEMORY

WRITE

FETCH

EXECUTE

MEMORY

WRITE

FETCH

EXECUTE

MEMORY

WRITE

FETCH

EXECUTE

MEMORY

WRITE

疎結合のパイプラインの例(AXI-Stream)

各モジュールは独立しており必要な情報はすべて流さないといけない

他のモジュール内の情報の参照ができない(疎結合)

今後はMPI とか OpenMPを研究予定

おまけ: for 文

• for 文 + 配列は、スケジューリングの中でうま

く対応すればパイプライン化が見込めやすい比較的まれな例(だとおもう)

–でも配列の参照方法や順序などをチェックしないといけないので大変

–そう意味では foreach文は、コンパイラにとってシリアライズが確定するので大変助かる構文

まわりくどくなりましたがそれを踏まえて

Polyphony の新機能の紹介

Polyphony:並列プログラミング

並列計算モデルを構築するための道具を用意

●Module●Worker●Port

並列プログラミング

Module

●回路全体またはその一部を表す単位●外部入出力のためのPortを持つ●さまざま処理を独立して行う複数のWorkerを持つ

並列プログラミング

Worker

●Moduleに含まれる並列動作する処理の単位●入出力のためのPortを持つ●Workerの持つPortは外部もしくは内部(別の

Worker)と接続

並列プログラミング

Port

●データのやり取りを行うためのチャネル●ModuleおよびWorkerの入出力になる●単一データ用のPortとFIFOとして動作する

Queueがある

並列プログラミング

例:@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)

おしまい

Githubhttps://github.com/ktok07b6/polyphony

top related