プログラミング言語のパラダイムシフト(ダイジェスト)ーscalaから見る関数型と並列性時代の幕開けー...

33
プログラミング言語の パラダイムシフト Scalaから見る関数型と並列性時代の幕開け 安田裕介 Hackers Champloo 2015 LT

Upload: tanukkii

Post on 21-Apr-2017

8.419 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

プログラミング言語のパラダイムシフト

Scalaから見る関数型と並列性時代の幕開け

安田裕介Hackers Champloo 2015 LT

Page 2: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

自己紹介

• 名前:安田裕介

• id: TanUkkii

• トライフォート勤務

Page 3: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

今日話す内容

• なぜ並列分散プログラミングが重要なのか

• Scalaから見る並列分散プログラミングの現状

• このダイジェスト版 (http://www.slideshare.net/TanUkkii/functional-and-concurencyinscala)

Page 4: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

concurrency なぜ並列性なのか

Page 5: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

ムーアの法則

http://spray.io/duse/#/2

トランジスタの数は1.5年ごとに倍になる

Page 6: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

ムーアの法則

http://spray.io/duse/#/2

単一スレッドの パフォーマンスは 限界に達した

今後は コアが増える形で トランジスタの集積率を 増やす形になる

トランジスタの数は1.5年ごとに倍になる

Page 7: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

アムダールの法則

http://spray.io/duse/#/3

並列計算の分野において、複数のプロセッサを使ったときの 理論上の性能向上の限界を予測する法則

Page 8: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

アムダールの法則

並列性の低い プログラムは コアが増えても まったく速くならず、 リソースを無駄にする

並列性の高い プログラムは コアが増えるほど 速くなる

http://spray.io/duse/#/3

並列計算の分野において、複数のプロセッサを使ったときの 理論上の性能向上の限界を予測する法則

Page 9: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

並列性の低いアプリケーションは CPUを使い切れない

PHP + Apache CPU: 32コア Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz

Page 10: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

ハードウェアの進化を 待っていれば

プログラムが速くなる 時代は終わった

Page 11: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

時代は 並列分散プログラミングへ

Page 12: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

並列分散処理の技術

http://spray.io/duse/#/5

Page 13: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

スレッド

http://spray.io/duse/#/5

Page 14: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

スレッドの問題• 原子性がない

• 順番の保証がない

• デッドロック、レースコンディション

• リソースとして貴重

• 排他制御、待ち合わせなど、コードが複雑になる

• デバッグが困難

Page 15: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

並列分散処理は 難しすぎる

早くなんとかしないと…

万人のための並列分散処理の課題

Page 16: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Scalaはこう解決(しようと)してる

Page 17: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Future

http://spray.io/duse/#/5

Page 18: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Future

• 非同期計算の結果のための統一インターフェースとしてのコレクション

• Scalaにおける並列実行の単位

• map, flatMapなどのモナドコンビネーターメソッド搭載

Page 19: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

"Future" must { import scala.concurrent.ExecutionContext.Implicits.global "map and flatMap" in { val futureMessage = Future { Thread.sleep(1000); 1 }.flatMap(value => Future { Thread.sleep(1000); value + 1 }).map(s => s"This is a value of future after $s seconds") Await.result(futureMessage, 5 seconds) must be("This is a value of future after 2 seconds") } "for comprehension" in { val futureMessage = for { s1 <- Future { Thread.sleep(1000); 1 } s2 <- Future { Thread.sleep(1000); s1 + 1 } } yield s"This is a value of future after $s2 seconds" Await.result(futureMessage, 5 seconds) must be("This is a value of future after 2 seconds") }}

Future

並列に実行

並列に実行 並列に実行

forコンプリヘンション

並列に実行並列に実行

Page 20: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Parallel Collection

http://spray.io/duse/#/5

Page 21: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

• Scalaコレクションの並列版

• Scalaコレクションと同じAPIだが、内部実行は並列

• parメソッドによりScalaコレクションから並列コレクションに透過的に変換できる

• Scalaコレクションと使いかたが同じなので簡単に使える

Parallel Collection

Page 22: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Parallel Collection

"parallel collection" must { "behave same as standard one" in { val list = (0 to 9999).toList list.map(_ + 1).filter(_ % 2 == 0).fold(0)(_ + _) must be list.par.map(_ + 1).filter(_ % 2 == 0).fold(0)(_ + _) }}

通常のコレクション

並列コレクション

使い方まったく同じ

Page 23: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Actor

http://spray.io/duse/#/5

Page 24: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Actorとは

• 並列実行単位となるオブジェクト

Future: 関数 Actor: オブジェクト並列実行単位

Page 25: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Actor の仕組みmailbox

thread pool

partial function

message

event loop

thread

Page 26: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Actorはスレッドの問題を解決する

• 原子性:アクター内部の処理は並列ではなく順次実行されるので、通常のプログラミングと同じ

• 実行順序:アクター内部の処理は並列ではなく順次実行されるので、通常のプログラミングと同じ

• カプセル化:他のスレッドからアクター内はアクセスできない

• 安全性:アクターはブロックしないので、デッドロックはおきない

• リソース効率性:スレッドプールから論理スレッドが確保できたときだけ、メッセージが処理される

Page 27: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Actorによる並列プログラミングclass CountAActor extends Actor { var totalA = 0 def receive: Receive = { case "How many?" => sender ! totalA case text: String => totalA += text.toUpperCase().count(_ == 'A') }} object CountAActor { def props = Props(new CountAActor)}

class SampleTest extends TestKit(ActorSystem("SampleSystem", ConfigFactory.empty()))with WordSpecLike with MustMatchers with ImplicitSender with StopSystemAfterAll { "CountAActor" must { "count A and a" in { val countAActor = system.actorOf(CountAActor.props, "countAActor") countAActor ! "na" * 16 countAActor ! "BATMAN!" countAActor ! "How many?" expectMsg(18) } }}

非同期にメッセージを送る

必ず18になる

Actor内部は順次実行されるので、 安全に状態を更新できる

(直ちに処理されるのではなくmailboxに貯まる)

内部状態は絶対に外から見えないので、 他のスレッドから守られている

Page 28: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Pros & Cons• Future: 汎用的。スケールしない。

• Parallel Collection: 使い方簡単。利用機会は限定的。

• Actor: 高機能・高性能。プリミティブすぎて使いにくい (生成したら消すとか、メッセージの流れ道の組み合わせとか、全部自分でやる)。

Page 29: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Reactive Stream

http://spray.io/duse/#/5

Page 30: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Reactive Streamは未来

http://spray.io/duse/#/5

より汎用的に使えて、 抽象度が高く敷居が低い

この領域が未来

Page 31: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Reactive Streamとは?

https://speakerdeck.com/okapies/reactive-streams-ru-men-number-jjug

これ見て(ごめんなさい)

Page 32: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

Reactive Stream実装

Akka Stream

https://speakerdeck.com/okapies/reactive-streams-ru-men-number-jjug

こう書ける (らしい)

Page 33: プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー

まとめ• 今後CPUの進化はマルチコア化が駆動

• CPUを使い尽くすために、並列分散プログラミングが必要

• 並列分散プログラミングは難しい

• 抽象度・一般性のトレードオフの中で、並列処理のハードルを下げる様々な概念がある

• Future, Parallel Collection, Actor, Reactive Stream