Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
rzmq で
並列分散コンピューティング
(自称) ZeroMQエバンジェリスト 礒部正幸
(@chiral)
自己紹介
• R歴 約2年、TokyoR参加歴 約1年半
• 本業はソフト開発エンジニア
• アドテクベンチャーを起業(まだひとりで奮闘中)
– アドサーバ、DSP, 3PAS, DMPを作っています。
最近のヒット作
ZeroMQ
• 低レイテンシかつスケーラブルなトランスポートライブラリ
– 「メッセージキュー付きのソケット」のようなもの
• アクターモデル的な実装が可能になる
• プロセス内(スレッド間)、プロセス間(同一ホスト、別ホスト)のいずれにも対応
– 豊富な言語にバインディングが存在
• 言語間のインテグレーションが容易
• オープンソース(LGPL)
• ピアの基本パターンを組み合わせることにより、豊富な分散処理形態に
対応できる(スケーラブル)
Pub Sub
Sub
Sub
Pub-Sub Push-Pull
Push Pull
Pull
Pull
Req Rep
Req-Res
rzmqパッケージ
• ZeroMQのRバインディング
• 同一マシン上、別マシン間で、簡単にデータのやり取りが出来る
• RとR、Rと別の言語、いずれでもデータをやり取りできる
rzmq
ZeroMQ
rzmq
ZeroMQ
pyzmq
ZeroMQ
【1】 同じマシン上でRとRをつなぐ
プロセス1(Rを起動) プロセス2(Rを起動)
library(‘rzmq’)
context = init.context()
sock1 = init.socket(context, “ZMQ_PULL”)
bind.socket(sock1, “ipc:///test”)
receive.socket(sock1)
library(‘rzmq’)
context = init.context()
sock1 = init.socket(context, “ZMQ_PUSH”)
connect.socket(sock1, “ipc:///test”)
send.socket(sock1,“hoge”)
[1] "hoge"
文字列の転送
receive.socket(sock1)
receive.socket(sock1)
x <- 3.14
y <- 1:5
send.socket(socket, x)
send.socket(socket, y)
数値データ
の転送
[1] 3.14
[1] 1 2 3 4 5
なんと関数
の転送も可能
f <- function(n) n*365
send.send(socket, f)
send.send(socket, f)
receive.socket(sock1)
f <- receive.socket(sock1)
f(10)
function(n) n*365
[1] 3650
(参考) 逆方向にデータを送りたいときは、もう一組のPUSH-PULLソケットを作成する
ちゃんと関数を使える
【2】 別マシン間でRとRをつなぐ
ホストAのプロセス(Rを起動) ホストBのプロセス(Rを起動)
library(‘rzmq’)
context = init.context()
sock1 = init.socket(context, “ZMQ_PULL”)
bind.socket(sock1, “tcp://*:1234”)
receive.socket(sock1)
library(‘rzmq’)
context = init.context()
sock1 = init.socket(context, “ZMQ_PUSH”)
connect.socket(sock1, “tcp:///192.168.10.1:1234”)
send.socket(sock1,“hoge”)
[1] "hoge"
(参考) 両マシン上のRに同じパッケージが入っていれば、パッケージ関数の呼び出しは可能
ただし送れるのはピュアRのデータだけであり、パッケージの内部(C言語のメモリ)に
持っているデータは送ることができない。
以下、前頁と同様に数値データや関数を送受信できる
違いはここだけ
192.168.10.1 192.168.10.2
ポート1234
【3】 Rと他言語をつなぐ
library(‘rzmq’)
library(‘rjson’)
context = init.context()
sock1 = init.socket(context, “ZMQ_PULL”)
sock2 = init.socket(context, “ZMQ_PUSH”)
bind.socket(sock1, “ipc:///test1”)
bind.socket(sock2, “ipc:///test2”)
while(1) {
json<-receive.string(sock1)
dat <- fromJSON(json)
res <- some_calculate(dat)
send.string(sock2, toJSON(res))
}
R
Python
import zmq
import json
context = zmq.Context()
sock1 = context.socket(zmq.PUSH)
sock1.connect(“ipc:///test1”)
sock2 = context.socket(zmq.PULL)
sock2.connect(“ipc:///test2”)
sock1.send(json.dumps([1,2,[3]])
res=json.loads(sock2.recv())
JSONで
やりとり
(用途例)
* WebサービスのバックエンドでRを動かして分析機能を実現
* バッチ集計の一部でデータマイニングのところをRで実行
* Rから、前処理の部分をPerlやPythonで行う
* Rとscipyやscikit-learnを連携
* zeromqのfluent-plugin を使って、Rからfluentdでログデータを転送
(ちなみにJSONじゃなくてMsgPackで通信する方法があるか試したがうまくいかなかった)
var zmq = require(‘zmq’)
, sock1 = zmq.socket(‘push’)
, sock2 = zmq.socket(‘pull’);
sock1 = context.socket(zmq.PUSH);
sock1.connect(“ipc:///test1”);
sock2 = context.socket(zmq.PULL);
sock2.connect(“ipc:///test2”);
sock1.send(JSON.stringify([1,2,[3]]));
sock2.on(‘message’, function(msg) {
res = JSON.parse(msg);
});
Node.js
Perl
Ruby
以下、なんでも
【4】 AWSでスピードテストやってみた
スタンドアロン
(Rのプロセス1個)
一様乱数でx*x+y*y < 1 な割合でπ/4を求める
→ 4倍してπを得る
よくあるやつ
○ 実験の設定
・乱数の数N = 100000000 (1億)
・スタンドアロンのプログラムと、マスタスレーブ型の構成で速度を比較
・8コア26ECUのAWS EC2 M3ダブルエクストララージインスタンスで検証
・スレーブはN/10000(1万)単位のタスクを割り振る
スレーブ
(Rのプロセス)
マスター
(Rのプロセス)
https://gist.github.com/chiral/5689735
実験に使ったソースコード
比較
【4’】 AWSでスピードテストやってみた
実行結果
8CPUで6倍くらい速くなった!
【5】 まとめ
ZeroMQ(rzmq)を使えばマルチコアCPUをフルに活用できる!
ZeroMQ(rzmq)を使えば複数台のPCでスケールアウトができる!
さらに、ZeroMQ(rzmq)とJSONで他の言語とも連携ができる!
前処理は“P系“言語で、データ分析はRで、役割分担!
Webサービスのバックエンドで簡単にRを使える!
数値や文字列だけでなく関数も送受信できる!
じゃあ
ZeroMQ(rzmq)
いつ使うの?
おわりに
ヒント: 「今」

More Related Content

rzmq