ジャパネットqb gpars
TRANSCRIPT
ジャパネットQB
2011/02/24 at G*ワークショップ
ジャパネットQB
GParsで並行プログラミング
一部元ネタを知らないと楽しめないところがございますが、
ご了承願います m(_ _)m
こんばんは、ジャパネットQBの時間だよ。
今日紹介する商品は、GParsだよ、まどか。
お前、誰よ
名前:キュゥべえ(QB)出身:『魔法少女まどか☆マギカ』(MBS,TBS,CBC)特徴:腹黒口癖:「僕と契約してよ。」
ねぇ QB、GParsって何なの?
GPars(Groovy Parallel Systems)ってね、Groovyベースの
並行処理ライブラリのことだよ。
近年のCPUの進化って、クロックアップよりも
マルチコア・メニーコア化の方が中心だよね。
プログラミングもマルチコアを活用すべく、
並行プログラミングが意識されるようになったんだ。
まどかは、並行プログラミングって
どうしてる?
えっ…java.lang.Threadと
java.lang.Runnableと synchronizedしか…
私は、java.util.concurrentパッケージの
ExecutorServiceやFuture、CountDownLatchね。
でもね、Java APIだけで並行プログラミングって
なかなか難しいと思わない?
そこで、GParsの出番さ。
GParsは、様々な言語の並行モデルや調整モデルを
取り込んでいるんだ。
・JavaのExecutorやFork/Join・ErlangやScalaのActor・ClojureのAgent・OzのDataflow Variable
これらのモデルをGroovyをベースに
使いやすく書きやすいように上手くDSL化してるんだ。
GParsのURLはhttp://gpars.codehaus.org/
最新バージョンは0.11、昔はGParallelizerって呼ばれてたんだよ。
僕と契約してみたく...GParsを使ってみたくなったでしょ?
えっ…でも、インストールとか
大変でしょ?
そんなことないよ。Groovy 1.8.0-beta-4から
GParsのライブラリがバンドルされるようになったんだ。
Groovyをインストールするだけで、GParsも使えるようになるんだ。
そんな説明だけでは、ピンと来ないわね。
じゃあ、簡単にだけど、GParsの持つ機能を
いくつか紹介するね。
まず、並列コレクション。コレクションに対する操作を
並列に行うことができるんだ。
並列コレクションimport static groovyx.gpars.GParsPool.withPool
def nums = 1..100000withPool(5) { def squares = nums. collectParallel{ it ** 2 }. grepParallel{ it % 7 == it % 5 }. grepParallel{ it % 3 == 0 } println squares[0..3] + "..." + squares[-3..-1] assert squares[0..3] == [36, 144, 1089, 1296]}
さっきの例は、もう少し簡潔に書けるんだ。
並列コレクションimport static groovyx.gpars.GParsPool.withPool
def nums = 1..100000withPool(5) { def squares = nums.parallel. map{ it ** 2 }. filter{ it % 7 == it % 5 }. filter{ it % 3 == 0 }. collection println squares[0..3] + "..." + squares[-3..-1] assert squares[0..3] == [36, 144, 1089, 1296]}
次は、Fork/Join。分割統治的な処理を
することができるんだ。
Fork/Joinimport static groovyx.gpars.GParsPool.withPoolimport static groovyx.gpars.GParsPool.runForkJoin
def quicksort(numbers) { withPool { runForkJoin(0, numbers) {index, list -> def groups = list.groupBy { it <=> list[list.size().intdiv(2)]} if ((list.size() < 2) || (groups.size() == 1)) { return [index: index, list: list.clone()] } (-1..1).each { forkOffChild(it, groups[it] ?: [])} return [index: index, list: childrenResults.sort {it.index}.sum {it.list}] }.list }}
次は、Closureの非同期実行。Closureを簡単に
非同期実行するんだ。
Closureの非同期実行import static groovyx.gpars.GParsExecutorsPool.withPool
withPool { // 同期 assert 6 == {it * 2}.call(3) // 非同期 assert 6 == {it * 2}.callAsync(3).get()}
次は、Actor。メールボックスの
メッセージを使用する軽量のプロセスだね。
Actorimport static groovyx.gpars.actor.Actors.actor
def decryptor = actor { react {message -> reply message.reverse() }}def console = actor { react { println 'Decrypted message: ' + it }}
decryptor.send 'lellarap si yvoorG', consoleconsole.join()
次は、Agent。オブジェクトに
スレッドセーフにアクセスするための仕組みだよ。
Agentimport static groovyx.gpars.agent.Agent
def jugMembers = new Agent<List<String>>(['Me'])
jugMembers.send {it.add 'James'}
final Thread t1 = Thread.start { jugMembers << {it.add 'Joe'}}
final Thread t2 = Thread.start { jugMembers {it.add 'Dave'} jugMembers {it.add 'Alice'}}
[t1, t2]*.join()println jugMembers.valjugMembers.valAsync {println "Current members: $it"}
jugMembers.await()
最後は、Dataflow変数。変数へのバインドで
処理を協調的に行うんだ。
Dataflow変数import static groovyx.gpars.dataflow.DataFlowVariableimport static groovyx.gpars.dataflow.DataFlow.task
final def x = new DataFlowVariable()final def y = new DataFlowVariable()final def z = new DataFlowVariable()
task { z << x.val + y.val println "Result: ${z.val}"}
task { x << 10}
task { y << 5}
ねぇ、どうだった、まどか?並行プログラミングをする時は
GParsを使ってみるといいかも。
お約束
でも・・・高いんでしょ?
Apache 2 ライセンスのオープンソースだよ。
だから、僕と契約して、魔法少女になってよ。
Groovy使いになってよ。
でも、クーリングオフはできないからね。
ジャパネットQB
完