SlideShare a Scribd company logo
Mulvery
CPU+FPGAプラットフォームのための
Rubyベースの開発環境
2017年度 未踏事業 クリエータ
まるさ
沖縄Ruby会議 02
2018/03/10
自己紹介
まるさ(照屋大地)
2017年度未踏事業
クリエータ
東京農工大学 工学府
情報工学専攻 M1
Rubyを始めたのは1年前
_人人人人_
> 1年前 <
 ̄Y^Y^Y ̄
2018/03/10
なプログラムを
どえらく速くする
アジェンダ
1. Mulveryの概要ときっかけ
2. ReactiveXとハード合成のアイデア
3. 未踏での開発
• ハード合成の仕組みの試行錯誤
• ラムダ抽象の合成
• Schedulerの合成
• ソフト/ハードの連携
4. 余談
5. さいごに
2018/03/10
マイコン Internet
きっかけ:IoTデバイス開発の課題
2017/7/1 5
多数の高速な
外部I/Oを扱いたい
センサデバイス
FPGA Internet
2017/7/1 6
内部の論理回路を自由に
組み換え可能なチップ
「処理のハードウェア化」
ネットワークに
接続したい
きっかけ:IoTデバイス開発の課題センサデバイス
マイ
コン
FPGA Internet
2017/7/1 7
多数の高速な
外部I/Oを扱いたい
ネットワークに
接続したい
CPU+FPGA環境
におけるシステム開発の簡略化がしたい!
きっかけ:IoTデバイス開発の課題センサデバイス
連携が面倒
マイ
コン
FPGA Internet
2017/7/1 8
多数の高速な
外部I/Oを扱いたい
ネットワークに
接続したい
CPU+FPGA環境
におけるシステム開発の簡略化がしたい!
きっかけ:IoTデバイス開発の課題センサデバイス
連携が面倒
“ぜんぶRubyだけでサクサク書きたい”
Mulveryプロジェクト
これまでに作ってきたもの
2018/03/03 9
高専ロボコン(’10~)
高専プロコン(‘11~)
Android開発(‘12~)
電気自動車ECU(‘13)
自律分散システム
(’15~)
FPGA開発支援環境
(’16~)
もっと早くFPGAに
気づけたら・・・
システムづくりデビュー
2018/03/03 10
賢く可視化、簡単節電
かしこん!!
(2012年度高専プロコン 自由部門)
通信+センシングは
つらい・・・
PLC
メモリ
CPU
FPGA
デバイス
ドライバ
ソフトウェア
ソフトウェア
ソースコード群
ハードウェア
制約ファイル
ハードウェア
設計ファイル
ハードウェア
ソースコード群
Network
ソフトウェア
開発するシステム
ハードウェア
開発段階
これまでのCPU+FPGA環境
課題1
幅広い知識が必要
2018/03/10
set_directive_pipeline
“Interface::get_data
/get_data_loop0”
高位合成とその複雑さ
• 高位合成(High Level Synthesis, HLS)
CやJava等の高級言語を,ハードウェア記述言語(HDL)
によるレジスタ転送レベル(RTL)設計に変換する技術
ビヘイビア
記述
(高級言語)
最適化
指示の記述
(専用命令)
高位合成系
RTL設計
(HDL)
シミュレータ
による評価
FPGA
課題2
「動作記述≠構造記述」
→HW技術者による最適化が必要
2018/03/10
CPU
FPGA
目指すところ
2018/03/10
Internet
ソフトウェア
開発段階 開発するシステム
ハードウェア
Mulvery
フレームワーク
Ruby
ソースコード
ハード化対象を
自動で抽出
回路設計の
知識不要
セ
ン
サ
(
ア
ク
チ
ュ
エ
ー
タ
)
CPU
FPGA
データ処理のアクセラレータにも
2018/03/10
Internet
ソフトウェア
開発するシステム
ハードウェア
ネットワーク接続,
データのパース・整形,
条件分岐の多い処理, ...
ストリームデータの
アグリゲーション, 操作,
並列処理, ...
マイコン+FPGAな環境?
Trenz Electronics社
“Zynqberry”
簡単に書けても
環境がない・・・
マイコン+FPGAな
Raspberry Pi
互換ボード
15
マイコン+FPGAな環境?
Trenz Electronics社
“Zynqberry”
ラズパイで
できるのか!
マイコン+FPGAな
Raspberry Pi
互換ボード
16
PythonでFPGAを便利に使うヤツ
2018/03/10
• ハードウェアをAPI的にPythonから呼び出せる
• SDK+ハードウェア
• ハードは専門家が作る
• DeepLearningや
リアルタイム画像処理
で遊べる こういうの
Rubyにもほしい!
ReactiveXと
ハード合成のアイデア
2018/03/10
Mulveryのアプローチ
2018/03/10
Reactive Programmin (RP)
「データストリーム」をオブジェクトとして扱う
プログラミングパラダイム
Reactive Programmingを用いたプログラムからの合成
Web開発
Web開発
Android開発
今回は
Rxを使ったコードを
速くする
ReactiveXとは
• Observer Pattern …
• LINQ …………………
• Scheduler ……………
2018/03/10
次の3つの要素を組み合わせて
データフローを記述してプログラムを作る
非同期の実現
操作クエリの実装
スケジューリング
Reactive Programmingの例
2018/03/10
time
map( event becomes 1 )
1 1 1 1
1 2 3 4
scan(+)
Source
map
scan
・データの到着回数を数える例:
Data Flow
Events
Observable
Observer Pattern
• Publish/Subscribeとも
• ObserverがSubjectを観察する
• RxではSubject=Observable
2018/03/10
ライブラリ側
ユーザ実装
イベントを
配信
イベントを
購読
Observer PatternとHW合成アイデア
2018/03/10
class Pin < SubjectBase
<pin_watcherの定義>
def notify(event)
@observers.each do |o|
o.onNotify(event)
end
end
def genHardware
<genHardwareの定義>
...
Observer1
ハードウェア
Observer2
ハードウェア
…
pin_watcher
ハードウェア
Pin pin_0
pin_0.addObserver do |e|
<Observer1の定義>
end
pin_0.addObserver do |e|
<Observer2の定義>
end
LINQ
• Language-INtegrated Query
• データ列(DBとか)を操作するための標準クエリ
2018/03/10
LINQ
• Language-INtegrated Query
• データ列(DBとか)を操作するための標準クエリ
2018/03/10
ラムダ抽象の内容を各イベントに適用
図:Rxのページより
LINQ
• Language-INtegrated Query
• データ列(DBとか)を操作するための標準クエリ
2018/03/10
イベントをバッファして1つのイベントにする
図:Rxのページより
LINQ
• Language-INtegrated Query
• データ列(DBとか)を操作するための標準クエリ
2018/03/10
2つのデータフローを待ち合わせる
図:Rxのページより
LINQ
• Language-INtegrated Query
• データ列(DBとか)を操作するための標準クエリ
2018/03/10
一定時間後にイベントを発生させる
図:Rxのページより
LINQ on Reactive Extensions
2018/03/10
LINQとHW合成アイデア
2018/03/10
time
map( event becomes 1 )
1 1 1 1
1 2 3 4
scan(+)
Source
map HW
scan HW
・データの到着回数を数える例(再掲)
各HWは
HDLのテンプレート
から合成
Events
Observable
Scheduler
• 動作スレッドを制御するための仕組み
• たとえばTimerだと・・・
2018/03/10
o1 = Observable.timer(1) do
p “this is o1”
end
o2 = Observable.timer(1) do
p “this is o2”
end
Current
Thread
Local
Thread
Local
Thread
this is
o1
this is
o2
timer(len,
scheduler=DefaultScheduler)
使い方に応じてschedulerを変える
Scheduler
2018/03/10
m_th = LocalScheduler.new
o1 = Observable.timer(1, m_th) do
p “this is o1”
end
o2 = Observable.timer(1, m_th) do
p “this is o2”
end
Current
Thread
Local
Thread
this is
o1
this is
o2
• 同一スレッドで時間計測させる例
SchedulerBaseを使って
任意の戦略が実装可能
SchedulerとHW合成アイデア
2018/03/10
Current
Thread
Local
Thread
this is
o1
this is
o2
• 動的スケジューリングを制限すれば
そのままデータフローグラフとして扱えそう
Source
o1 HW
o2 HW
Current
Thread
HW
未踏での開発
2018/03/10
実装しなければならないもの
1. HW抽出機構
2. HW合成機構
3. ラムダ抽象の合成
4. Schedulerの合成
5. ソフト/ハード連携
2018/03/10
V2:動的解析による実装
• 多段階計算を使った動的解析の実装への舵切り
• フレームワークとして提供するので
通常のRubyで合成も実行も全部できる
2018/03/10
ハード/ソフトの自動分割
I2C Bus A
groupBy
averag
e
averag
e
0x1234 0x5678
データフローグラフ
def initialize()
i2c_stream = Stream.new(I2C_BUS_A)
sensors = i2c_stream.group_by(2)
{ |d| d. sensor_ id }
for sensor in sensors do
@averages[sensor] =sensor.average(5)
end
end
def main()
for average in @averages do
p average[sensor].get_latest()
end
wait_ms(100)
end
ソフトウェア部ハードウェア部
sensors[A] Sensors[B]
averages[B]averages[A]
i2c_stream
Rxで書きにくい部分は
多く場合ソフト実行が速い
Rx記述⇒ハード それ以外⇒ソフト
ハード化
メモリに
マップ
2018/03/10
ハードウェア合成の例
2018/03/10
events = Stream.new(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
Streamオブジェクトが
ハードウェアを生成する
ハードウェア合成の例
2018/03/10
events = Stream.new(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
module S_0(p0);
…
endmodule
Streamオブジェクトが
ハードウェアを生成する
S_0.v
ハードウェア合成の例
2018/03/10
events = Stream.new(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
module S_0(p0);
…
Map_0 map_0(
.din(w_0_0),
.v_din(v_w_0_0),
.dout(w_0_1),
.v_dout(v_w_0_1));
endmodule
module Map_0(…);
…
dout <= 8’d1;
v_din <= 1’b1;
…
endmodule
Streamオブジェクトが
ハードウェアを生成する
Map_0.vS_0.v
テンプレート
から生成
ハードウェア合成の例
2018/03/10
events = Stream.new(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
module S_0(p0);
…
Map_0 map_0(
.din(w_0_0),
.v_din(v_w_0_0),
.dout(w_0_1),
.v_dout(v_w_0_1));
Scan_0 scan_0(
…
endmodule
module Map_0(…);
…
dout <= 8’d1;
v_din <= 1’b1;
…
endmodule
Streamオブジェクトが
ハードウェアを生成する
module Scan_0(…);
…
endmodule
Scan_0.v
Map_0.vS_0.v
ハードウェア合成の例
2018/03/10
events = Stream.new(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
module S_0(p0);
…
Map_0 map_0(
.din(w_0_0),
.v_din(v_w_0_0),
.dout(w_0_1),
.v_dout(v_w_0_1));
Scan_0 scan_0(
…
endmodule
module Map_0(…);
…
dout <= 8’d1;
v_din <= 1’b1;
…
endmodule
Streamオブジェクトが
ハードウェアを生成する
module Scan_0(…);
…
endmodule
Scan_0.v
Map_0.vS_0.v
他にも・・・
・Topモジュール
・計算カーネル
etc…
実装しなければならないもの
1. HW抽出機構
2. HW合成機構
3. ラムダ抽象の合成
4. Schedulerの合成
5. ソフト/ハード連携
2018/03/10
✔
✔
ラムダ抽象の合成について
• LINQクエリの多くは高階関数
• ラムダ抽象の合成はどうしよう・・・
⇒現状は用途に合わせた
多段階計算で誤魔化している
2018/03/10
サンプル:畳み込み演算
• 128x128の画像に対するラプラシアンフィルタ適用
2018/03/10
∗ =
…
128画素
(1行)
…
…
…
…
…
入力バッファ 5行バッファ 畳み込みx128
…
128画素
(1行)
result
コーディング例
2018/03/10
buffer = input.sliding_buffer(5)
line = buffer.map(){ |data|
mats = Array.new()
for i in (0…SIZE) do
mats.push(Matrix[data[0][i, 5], ¥
data[1][i, 5], ¥
data[2][i, 5], ¥
data[3][i, 5], ¥
data[4][i, 5]])
end
result_row = Array.new()
mats.map() do |mat|
result_row.push(mat.conv(kernel))
end
}
result = line.buffer(128)
input
sliding_
buffer
map
buffer
5行ぶん待つ
5行毎に処理(畳み込み)
128行出力待つ
コーディング例
2018/03/10
buffer = input.sliding_buffer(5)
line = buffer.map(){ |data|
mats = Array.new()
for i in (0…SIZE) {
mats.push(Matrix[data[0][i, 5], ¥
data[1][i, 5], ¥
data[2][i, 5], ¥
data[3][i, 5], ¥
data[4][i, 5]])
}
result_row = Array.new()
mats.map() { |mat|
result_row.push(mat.conv(kernel))
}
}
result = line.buffer(128)
ラムダ抽象をメタプロ的に扱う
2018/03/10
buffer = input.sliding_buffer(5)
line = buffer.map(){ |data|
mats = Array.new()
for i in (0…SIZE) {
mats.push(Matrix[data[0][i, 5], ¥
data[1][i, 5], ¥
data[2][i, 5], ¥
data[3][i, 5], ¥
data[4][i, 5]])
}
result_row = Array.new()
mats.map() { |mat|
result_row.push(mat.conv(kernel))
}
}
result = line.buffer(128)
data
mats
Array, Matrixは
オーバーロード
されている
ラムダ抽象をメタプロ的に扱う
2018/03/10
buffer = input.sliding_buffer(5)
line = buffer.map(){ |data|
mats = Array.new()
for i in (0…SIZE) {
mats.push(Matrix[data[0][i, 5], ¥
data[1][i, 5], ¥
data[2][i, 5], ¥
data[3][i, 5], ¥
data[4][i, 5]])
}
result_row = Array.new()
mats.map() { |mat|
result_row.push(mat.conv(kernel))
}
}
result = line.buffer(128)
data
mats
mat
kernel
result_
row
(convolution)
IF文のハードウェア化
2018/03/10
line = buffer.map(){ |data|
check(data == 0) {
do_something_1()
}
.elsewhen(data == 1) {
do_something_2()
}
.otherwise {
do_something_3()
}
.endcheck
}
check
CheckContext#elsewhen
CheckContext#otherwise
CheckContext#endcheck
ハード合成時:すべて評価
ソフト実行時:IFとおなじ
実装しなければならないもの
1. HW抽出機構
2. HW合成機構
3. ラムダ抽象の合成
4. Schedulerの合成
5. ソフト/ハード連携
2018/03/10
✔
✔
✔
LocalThread_0
Schedulerの合成
2018/03/10
Current
Thread
Local
Thread
this is
o1
this is
o2
• Thread毎にステートマシンを持つ
• CurrentThreadは必ず生成する
o1 HW
o2 HW
CurrentThread
Current
Thread
HW
Schedulerの合成の問題
• 複数のThreadを同時にキックしたい場合
(未解決)
2018/03/10
o1 = Observable.timer(1) do
p “this is o1”
end
o2 = Observable.timer(1) do
p “this is o2”
end
Current
Thread
Local
Thread
Local
Thread
this is
o1
this is
o2
違うstateで
キックしてしまう
(1億分の2~3秒のズレ)
実装しなければならないもの
1. HW抽出機構
2. HW合成機構
3. ラムダ抽象の合成
4. Schedulerの合成
5. ソフト/ハード連携
2018/03/10
✔
✔
✔
✔
ソフト/ハード自動連携
• 現状はかなり素朴な実装
• 共有メモリでデータ共有のみ
2018/03/10
I2C Bus A
groupBy
averag
e
averag
e
0x1234 0x5678
データフローグラフ
sensors[A] Sensors[B]
averages[B]averages[A]
i2c_stream
ハード化
メモリに
マップ
ユーザアプリ(Ruby)
Ruby拡張
(C言語)
Debian
OS管理
メモリ
OS管理外
メモリ
メモリアクセス機構
Ruby
ライブラリ
Mulvery合成回路
外部I/O
Processing
System
Programmable
Logic
実装しなければならないもの
1. HW抽出機構
2. HW合成機構
3. ラムダ抽象の合成
4. Schedulerの合成
5. ソフト/ハード連携
2018/03/10
✔
✔
✔
✔
✔
Mulveryの
楽しいところ
2018/03/10
これまでのハードウェアオフロード
2018/03/10
__kernel void func(
__global int *data){ ... }
・オフロードする関数を指定する必要
・オフロードした関数はFPGA上で実行
Intel FPGA SDK
for OpenCL
透過性の高い記述
2018/03/10
def func(data)
…
end
stream_1 = Stream.new()
grouped_stream_1 = stream_1.group_by{|d| func(d)}
array_1 = [1, 2, 3, 4, 5, 6]
grouped_array_1 = array_1.group_by{|d| func(d)}
非Stream:
CPUで実行
Stream:
FPGAで実行
データに近い場所で処理が行われる
透過性の高い記述
透過性の高い記述の例2
2018/03/10
i2c_stream = Stream.new(I2C_BUS_A)
sensors = i2c_stream.group_by(2)
{ |d| d. sensor_ id }
averages = sensors.map{ |key, val|
[key, sensor.average(5)]
}.to_h()
I2C Bus A
i2c_stream
groupBy
average average
sensors[A] Sensors[B]
averages[B]averages[A]
同じメソッドが「ソフトウェア記述」
「ハードウェア記述」「generator文」の3役を果たす
⇒ハードにもソフトにもならないmap
デバイスコントローラとしての活用
1024個のフルカラーLED(NeoPixel)を制御してみる
マイコン
Web
Server
FPGA
LED制御
LED
マトリクス
マイコンだと
アセンブリが必要
akiba LED ピカリ館さんにて
1000個!?
一度にまとめて
動かせるんですか!?
1.25us信号
x24x1024
2018/03/10
Rubyの資産を使って
システム実装できる
用途の検討
工場IoTで使えるかも
⇒データアグリゲーションしたい
⇒でもオペレーションでFPGAは
触りたくない・・・
車やロボは難しい
⇒必ずプロがチューニング
プロユースと汎用マイコン
の境目にマーケット?
FPGAベンダのXilinx社を訪問
2018/03/10
余談
2018/03/10
ところで・・・
合宿の時:
Twitterでは:
micropython
mruby
Pythonのほうが
よいかも?
2018/03/10
なぜRubyなのか
Rubyの方が色々やりやすかった!
events = Stream.from_pin(MIO::p0)
t = events.map(lambda event: 1)
count = t.scan(lambda acc, x: acc + x)
VS
Python
・Method chainがしにくい
・ラムダ抽象が使いにくい
⇒イマイチ・・・
events = Stream.from_pin(MIO::p0)
count = events
.map(){ |event| 1 }
.scan(){ |acc, x| acc + x }
Ruby
・Method chainできる
・ラムダ抽象をブロックで
⇒かっこいい!
2018/03/10
自動テストの話
• RSpec+自作テスタ on Travis CI
2018/03/10
RSpecを用いた
各メソッド単体テスト
Makefileを使って
テストハードの合成
Icarus Verilogで
テストハードの動作検証
Vivadoでテストハードの
配置配線が通るかテスト
on 自宅サーバ
さいごに
2018/03/10
Mulveryのまとめ
・Rubyで
簡単にFPGA開発ができる
Rxからハード合成する技術を開発
チューニングコストを削減!
・多数の外部デバイス操作が得意
Webサーバを動かしつつLEDを
1024個同時に制御できた!
2018/03/10
2018/03/10
2018/03/10

More Related Content

PDF
Mulvery技術詳細
PDF
ArcGISの便利な印刷周りの機能に、QGIS APIを駆使して挑んでみたお話
PDF
QGISプログラミング入門 FOSS4G 2013 Hokkaido
PDF
Gdg geo2
KEY
GPGPU deいろんな問題解いてみた
PDF
121012 gisa qgis_handson
PPTX
CG2013 14
PDF
121215 foss4 g_nagoya_qgis_handson
Mulvery技術詳細
ArcGISの便利な印刷周りの機能に、QGIS APIを駆使して挑んでみたお話
QGISプログラミング入門 FOSS4G 2013 Hokkaido
Gdg geo2
GPGPU deいろんな問題解いてみた
121012 gisa qgis_handson
CG2013 14
121215 foss4 g_nagoya_qgis_handson

Similar to Mulvery@沖縄Ruby会議02 (20)

PDF
UnityとBlenderハンズオン第1章
PDF
わんくま同盟名古屋勉強会18回目 ASP.NET MVC3を利用したHTML5な画面開発~クラウドも有るよ!~
PDF
Node.jsでブラウザメッセンジャー
PDF
.NET の過去、現在、そして未来
PDF
20150209 甲府-web新世紀2
PDF
red-hat-forum-2017-openshift-baremetal-deployment
PDF
04 citynet awsセミナー_クラウドでビックデータのスモールスタート
PDF
クラウドでビックデータのスモールスタート
PDF
Android Lecture #01 @PRO&BSC Inc.
PDF
さくらのIoT Platformを使ってみよう ~OSC大阪編~
PDF
The Twelve-Factor (A|M)pp with C#
PDF
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
PDF
この Visualization がすごい2014 〜データ世界を彩るツール6選〜
PDF
Smart Tennis Lesson Serverless Design
PDF
ReduxとSwiftの組み合わせ:改訂版
PDF
さくらのIoT Platformを使ってみよう ~Developers in KOBE編~
PPTX
Azure のポータル画面で、AI フレーバな BOT の作成ハンズオン
PDF
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
PDF
日本発オープンソース!! スケールアウト型データベース GridDB入門 ~ GitHubからダウンロードして使ってみましょう ~
PPTX
Oculus Quest 2 on Mixed Reality Toolkit V2.5.0~ ハンドトラッキングする方法 ~
UnityとBlenderハンズオン第1章
わんくま同盟名古屋勉強会18回目 ASP.NET MVC3を利用したHTML5な画面開発~クラウドも有るよ!~
Node.jsでブラウザメッセンジャー
.NET の過去、現在、そして未来
20150209 甲府-web新世紀2
red-hat-forum-2017-openshift-baremetal-deployment
04 citynet awsセミナー_クラウドでビックデータのスモールスタート
クラウドでビックデータのスモールスタート
Android Lecture #01 @PRO&BSC Inc.
さくらのIoT Platformを使ってみよう ~OSC大阪編~
The Twelve-Factor (A|M)pp with C#
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
この Visualization がすごい2014 〜データ世界を彩るツール6選〜
Smart Tennis Lesson Serverless Design
ReduxとSwiftの組み合わせ:改訂版
さくらのIoT Platformを使ってみよう ~Developers in KOBE編~
Azure のポータル画面で、AI フレーバな BOT の作成ハンズオン
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
日本発オープンソース!! スケールアウト型データベース GridDB入門 ~ GitHubからダウンロードして使ってみましょう ~
Oculus Quest 2 on Mixed Reality Toolkit V2.5.0~ ハンドトラッキングする方法 ~
Ad

More from Daichi Teruya (6)

PDF
iMulvery -Mulveryの新機能のご紹介-
PDF
Mulvery Detail - English
PDF
IoTLT17
PDF
2017年度未踏事業最終成果報告
PPTX
(Lambdaだけで) 純LISPのような ナニかを作る
PPTX
Mado magisystemx hago3
iMulvery -Mulveryの新機能のご紹介-
Mulvery Detail - English
IoTLT17
2017年度未踏事業最終成果報告
(Lambdaだけで) 純LISPのような ナニかを作る
Mado magisystemx hago3
Ad

Mulvery@沖縄Ruby会議02