Groovyで学ぶプロセス代数 #jjug

33
Learning Process Calculate with CSP, Groovy, GPars in JJUG 2014.09.18 kyon_mm

description

JJUGでGroovyでCSPを使い始めることについて紹介しました。

Transcript of Groovyで学ぶプロセス代数 #jjug

Page 1: Groovyで学ぶプロセス代数 #jjug

Learning Process Calculate with CSP, Groovy, GPars

in JJUG 2014.09.18 kyon_mm

Page 2: Groovyで学ぶプロセス代数 #jjug

Self Introduction

きょん kyon_mm

テストアーキテクト 2年目

TDD/BDD, SCM, Agile, Softwaretest, SoftwareEngineering

なごや

基礎勉強会, SCMBC, Nagoya.Testing, Cafe.Testing

Page 3: Groovyで学ぶプロセス代数 #jjug

Agenda

the word of CSP

Good points

Try! GPars! Verify! FDR!

Page 4: Groovyで学ぶプロセス代数 #jjug

the word of CSP

Page 5: Groovyで学ぶプロセス代数 #jjug

CSP

並行処理のモデルとして利用されているプロセス代数の一例です。

プロセス代数の他の例としては、ご存知π計算だと思います。

太一(@ryushi)さんが名古屋に来たときにGoの話をしていたので、jjugの皆様もGoを知っていると思い、Goユーザには身近なCSPの話をしにきました。

Page 6: Groovyで学ぶプロセス代数 #jjug

CSP

Tony Hoareが考案したモデルで、いまや様々な言語やフレームワークに影響を与えています。Occamはもちろんですが、Erlangも影響を受けています。

並行処理関連で「チャネル」がうんたらとか言われたら、CSPかな?って思って聞くといいかもだよ!

Page 7: Groovyで学ぶプロセス代数 #jjug

Good points

Page 8: Groovyで学ぶプロセス代数 #jjug

Good points

研究者と実績がたくさん

逐次実行と並行実行の仕様を比較するツール

Groovy(もしくはJava)で実装できる

Page 9: Groovyで学ぶプロセス代数 #jjug

逐次実行と並行実行 の比較

並行実行を正しく仕様化するのは難しいと言われており、僕もよく間違います。

逐次実行だったらあまり間違わないところでも、並行実行にするだけで難しくなることがよくある。

Page 10: Groovyで学ぶプロセス代数 #jjug

逐次実行と並行実行 の比較

そこで、FDR(ツール)ですよ。CSPとほぼ同等の記法のスクリプトを入力とする検証ツール。

CSP記法で同じ結果を得るための「逐次実行の仕様」と「並行実行の仕様」両方を書く。

FDRにそれぞれを入力すると、どの程度同一か判定してくれる!

結果によっては、ライブロックフリー、デッドロックフリーなどが保証される!!

Page 11: Groovyで学ぶプロセス代数 #jjug

Groovyで書ける

CSPをJava実装したものがJCSPというライブラリとして後悔されていて、GParsはJCSPをラップしている!

Groovyに並行処理を書ける!

Page 12: Groovyで学ぶプロセス代数 #jjug

Try GPars

Page 13: Groovyで学ぶプロセス代数 #jjug

GPars

Groovyをインストールすれば入っています。

org.codehaus.gpars:gpars:1.2.1

JCSPスタイルで書く事も、GParsスタイルで書く事も可能。

GParsスタイル = DataFlowクラス系との組み合わせ

Page 14: Groovyで学ぶプロセス代数 #jjug

Sample

groovyx.gpars.plugAndPlayパッケージ配下に簡単なものがいくつか定義されているので、それらを使って、とりあえず動かしてみる事ができます

Page 15: Groovyで学ぶプロセス代数 #jjug

plugAndPlay classes

GConsole

GConsoleStringToInteger

GDelta2

GFixedDelay

GIdentity

GIntegrate

GNumbers

GObjectToConsoleString

GPairs

GParPrint

GPCopy

GPlus

GPrefix

GPrint

GSquares

GStatePairs

GSuccessor

GTail

Page 16: Groovyで学ぶプロセス代数 #jjug

class Executor implements CSProcess {

def out1

def out2

def random = new Random()

@Override

void run() {

while (true){

out1.write(random.nextInt() % 10)

out2.write(random.nextInt() % 10)

sleep(50L)

}

}

}

Page 17: Groovyで学ぶプロセス代数 #jjug

def channelA = Channel.one2one()

def channelB = Channel.one2one()

def channelC = Channel.one2one()

final def par = new PAR([

new Executor(out1: channelA.out(), out2: channelB.out()),

new GPlus(inChannel0: channelA.in(), inChannel1:channelB.in(), outChannel: channelC.out()),

new GPrint(inChannel: channelC.in(), heading: "足し算しちゃうよ?")

])

par.run()

Page 18: Groovyで学ぶプロセス代数 #jjug

JCSP,GPars

処理はCSProcessインターフェースの実装に書きます。これをプロセスといいます。

プロセスとプロセスのやり取りはチャネルを通してのみ行います。

1プロセス対Nプロセス、1チャネル対Nチャネルもあります。

Page 19: Groovyで学ぶプロセス代数 #jjug

JCSP,GPars

new PAR([someProcess,,,])とすることで、プロセス合成をしている。

制限がありますが、プロセス通信は1マシン内でも、マシン間でも出来ます。(夢がひろがる!

Page 20: Groovyで学ぶプロセス代数 #jjug

例えばGSuccessorのなかみ↓

ChannelInput inChannel

ChannelOutput outChannel

void run() {

while (true) {

outChannel.write(inChannel.read() + 1)

}

}

Page 21: Groovyで学ぶプロセス代数 #jjug

例えばGPrintのなかみ↓

ChannelInput inChannel

String heading = "No Heading Provided"

long delay = 200

def void run() {

def timer = new CSTimer()

println "${heading}"

while (true) {

println inChannel.read().toString()

if (delay != 0) {

timer.sleep(delay)

Page 22: Groovyで学ぶプロセス代数 #jjug

CSP

チャネルは同期的に動作し、プロセスは非同期に動作する。(同期的メッセージング、非同期動作)

ただし、GParsではチャネルを非同期にすることもできる!(実際あやうい気はするが、わからない)

Page 23: Groovyで学ぶプロセス代数 #jjug

Sample with Dataflow

入力した文字列をフォーマットして、挨拶文を返すプログラム

Input <-> Formatter <-> Greeter <-> Output

Page 24: Groovyで学ぶプロセス代数 #jjug

class Formatter implements Callable<String> {

DataflowReadChannel rawNames

DataflowWriteChannel formattedNames

@Override

String call() {

while(!Thread.currentThread().isInterrupted()) {

String name = rawNames.val

formattedNames << name.toUpperCase()

}

}

}

Page 25: Groovyで学ぶプロセス代数 #jjug

class Greeter implements Callable<String> {

DataflowReadChannel names

DataflowWriteChannel greetings

@Override

String call() {

while(!Thread.currentThread().isInterrupted()) {

String name = names.val

greetings << "Hello " + name

}

}

}

Page 26: Groovyで学ぶプロセス代数 #jjug

def a = new SyncDataflowQueue()

def b = new SyncDataflowQueue()

def c = new SyncDataflowQueue()

!

group.task new Formatter(rawNames:a, formattedNames:b)

group.task new Greeter(names:b, greetings:c)

!

// 送信と受信をする

a << “Joe" // チャネルに送信

println c.val // 出力

Page 27: Groovyで学ぶプロセス代数 #jjug

Verify FDR

Page 28: Groovyで学ぶプロセス代数 #jjug

FDR3 Released!

書籍やなんかではFDR2!と書かれていますが、現在はFDR3.10がリリースされています。

FDRは学術目的のみ無償で利用できるライセンスです。

Page 29: Groovyで学ぶプロセス代数 #jjug

FDR3

みてみよう!

http://www.cs.ox.ac.uk/projects/fdr/

FDR3 で 検索!

Page 30: Groovyで学ぶプロセス代数 #jjug

Conclusion

Page 31: Groovyで学ぶプロセス代数 #jjug

Conclusion

CSPを使ってみたいなら、GParsを使うと簡単なプロセスがいくつか定義されているので、動かしやすいし、Groovy自体の書きやすさもあってよい。

モデルとコードが近くなりやすいCSPで書いておくと、ツールでの検証が捗るし、検証してからコードに書くのもそんなに困らない。

机上デバッグやめたいれす^q^

Page 32: Groovyで学ぶプロセス代数 #jjug

Append

非同期処理のプロジェクトで失敗したのをキッカケに真面目に取り組み始めました。

いまは、CSPベースの何かを開発しています。

CIサーバ

テスティングフレームワーク

ビルドツール

Page 33: Groovyで学ぶプロセス代数 #jjug

ご清聴ありがとぴょん◆