Successfully reported this slideshow.
ClojureではじめるSTM入門      @athos0220    並列/並行基礎勉強会
自己紹介@athos0220趣味でClojure触ってます正直STMとかまともに使ったことないわー付け焼刃に勉強したので間違ってるところあるかも(´・ω・`)→生温かくご指摘お願いします
What’s STM?
STMとはSoftware Transactional Memoryソフトウェアトランザクショナルメモリは、データベーストランザクションに似た並行性制御機構であり、並列計算を行う際の共有メモリへのアクセス法である。この機構はロックベースの同期を...
ロックの利点と欠点利点 いつロックを取得し、解除するかを陽に制御できる 開発者にとって馴染みがある方法 多くのプログラミング言語でサポートされている欠点 ロックのとる順序によってデッドロックが起こる 優先度逆転が起こる composableでない
STMの利点と欠点利点 デッドロックや優先度逆転が起きない 楽観的なので並行性が向上する composableである(ネストできる)欠点 リトライが頻発することでパフォーマンスが悪くなる 余分なオーバーヘッドがかかる トランザクション内では副作...
各言語での対応状況言語(処理系)組込み Clojure, Haskell, Perl6(Pugs)ライブラリ C, C++, C#, Common Lisp, Java, OCaml, Python, Scala, Smalltalkどの入門書...
How to use STM   in Clojure
STMの基本構文・関数(dosync <body>):<body>をトランザクションで実行(ref <val>):トランザクション内で変更が可能な参照(Ref型)を生成(deref <ref>):Refにくるまれた値をデリファレンス。@<ref...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              42  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              43  ...
STMを使ったコード                    (def counter (ref 42))                             counter                              44  ...
ClojureのSTM観       Thread A                              Thread B                            a... @a ...                  ...
ClojureのSTM観       Thread A                              Thread B                            a... @a ...                  ...
Under the hood of STM
Version Clockすべてのトランザクションで共有するクロックトランザクションの開始やリトライ、コミットのたびにインクリメントされる各トランザクションは自分が開始されたときのクロックの値を記録するコミット時にはそのときのクロックの値をRe...
RefいわゆるAtomic Object主に以下で構成されている 値の履歴をもつリングバッファ ref-setしたが未コミットのトランザクション Refを参照・更新する際に使われるロック
in-transaction valuesトランザクション内でアクセスしたRefとその値をローカルに記録する Refを更新するときはローカルな値を更新する Refから値を読み出すとき、  ローカルな値があればそれを読み出す  なければ、Refの...
MVCC多版型同時実行制御 (Multiversion Concurrency Control)  トランザクションの実行中、他のトランザクションが既に  更新した値を読み出すと一貫性がなくなる  これを防ぐには以下のような方法がある(2つめが...
write skew      MVCCで起こる現象      複数のトランザクション間で不変条件を破るような変更が行      われたときに発生                        不変条件                    @...
write skew      MVCCで起こる現象      複数のトランザクション間で不変条件を破るような変更が行      われたときに発生                        不変条件                    @...
ensure      write skewの問題は、暗に存在する「コミットする      まで変更されない」という条件が破られるために発      生する      Clojureでは (ensure <ref>) で、それ以降コミットが  ...
Contention management       Thread A                              Thread B                            a... @a ...         ...
Contention management       Thread A                              Thread B                            a... @a ...         ...
Contention management       Thread A                              Thread B                            a... @a ...         ...
Contention managementの戦略
Contention managementの戦略 Agressive: 相手を殺す
Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ
Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ Karma: あまり仕事をしていない方が死ぬ
Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ Karma: あまり仕事をしていない方が死ぬ Priority: 年功序列。若いやつが死ぬ
Contention managementの戦略    Agressive: 相手を殺す    Polite: 自分が死ぬ    Karma: あまり仕事をしていない方が死ぬ    Priority: 年功序列。若いやつが死ぬClojureのC...
まとめロックを使って同期するのは辛いSTM!STM! Clojureなら初心者でもSTM使えますただし、writeが多いと性能低下するなど、問題点もある → 銀の弾丸ではないしかし、将来的にはGCのように適用範囲は広がっていくのでは…?
参考文献M. Herlihy and N. Shavit. “The Art of Multiprocessor Programming,Revised Reprint.” Morgan Kaufmann Publishers Inc. 201...
Upcoming SlideShare
Loading in …5
×

ClojureではじめるSTM入門

8,023 views

Published on

Published in: Technology
  • Be the first to comment

ClojureではじめるSTM入門

  1. 1. ClojureではじめるSTM入門 @athos0220 並列/並行基礎勉強会
  2. 2. 自己紹介@athos0220趣味でClojure触ってます正直STMとかまともに使ったことないわー付け焼刃に勉強したので間違ってるところあるかも(´・ω・`)→生温かくご指摘お願いします
  3. 3. What’s STM?
  4. 4. STMとはSoftware Transactional Memoryソフトウェアトランザクショナルメモリは、データベーストランザクションに似た並行性制御機構であり、並列計算を行う際の共有メモリへのアクセス法である。この機構はロックベースの同期を用いた並行性制御の代替手段として機能し、ノンブロッキングな方法で実装される物もある。 Wikipediaより楽観的: 他のスレッドを気にせずとりあえず実行してみる 変なことになったらリトライする最近盛んに研究されている(らしい)
  5. 5. ロックの利点と欠点利点 いつロックを取得し、解除するかを陽に制御できる 開発者にとって馴染みがある方法 多くのプログラミング言語でサポートされている欠点 ロックのとる順序によってデッドロックが起こる 優先度逆転が起こる composableでない
  6. 6. STMの利点と欠点利点 デッドロックや優先度逆転が起きない 楽観的なので並行性が向上する composableである(ネストできる)欠点 リトライが頻発することでパフォーマンスが悪くなる 余分なオーバーヘッドがかかる トランザクション内では副作用を避ける必要がある
  7. 7. 各言語での対応状況言語(処理系)組込み Clojure, Haskell, Perl6(Pugs)ライブラリ C, C++, C#, Common Lisp, Java, OCaml, Python, Scala, Smalltalkどの入門書にもSTMの解説があるのはClojureだけ
  8. 8. How to use STM in Clojure
  9. 9. STMの基本構文・関数(dosync <body>):<body>をトランザクションで実行(ref <val>):トランザクション内で変更が可能な参照(Ref型)を生成(deref <ref>):Refにくるまれた値をデリファレンス。@<ref>は糖衣構文(ref-set <ref> <val>):Refの値を変更する。dosyncの外で使うとエラーになる
  10. 10. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v)))))
  11. 11. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v)))))
  12. 12. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 42
  13. 13. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 42 42
  14. 14. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43 42
  15. 15. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43 この時点の変更はBからは見えない 42
  16. 16. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43 42
  17. 17. STMを使ったコード (def counter (ref 42)) counter 42 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43 他で値が変更されていなければコミット 42
  18. 18. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43 コミット! 42
  19. 19. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 42
  20. 20. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43
  21. 21. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43
  22. 22. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v)))))Aが値を変更したので失敗 43
  23. 23. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) トランザクションを最初からやり直す 43
  24. 24. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43
  25. 25. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 43
  26. 26. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 44
  27. 27. STMを使ったコード (def counter (ref 42)) counter 43 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) 44
  28. 28. STMを使ったコード (def counter (ref 42)) counter 44 Thread A Thread B(dosync (dosync (let [v @counter] (let [v @counter] (when (<= v 100) (when (<= v 100) (ref-set counter (ref-set counter (inc v))))) (inc v))))) コミット! 44
  29. 29. ClojureのSTM観 Thread A Thread B a... @a ... ... (ref-set a ...) ...... (ref-set b ...) ... b ... (ref-set b ...) ... ... (ref-set c ...) ... c トランザクションは更新するRefを集めていく 途中で他のトランザクションが手を出しているRefに触ったらアボート →リトライ すべてのRefを集めて最後まで行ければゴール→コミット
  30. 30. ClojureのSTM観 Thread A Thread B a... @a ... ... (ref-set a ...) ...... (ref-set b ...) ... b ... (ref-set b ...) ... ... (ref-set c ...) ... c トランザクションは更新するRefを集めていく 途中で他のトランザクションが手を出しているRefに触ったらアボート →リトライ すべてのRefを集めて最後まで行ければゴール→コミットwriteが多いとリトライが頻発して性能低下
  31. 31. Under the hood of STM
  32. 32. Version Clockすべてのトランザクションで共有するクロックトランザクションの開始やリトライ、コミットのたびにインクリメントされる各トランザクションは自分が開始されたときのクロックの値を記録するコミット時にはそのときのクロックの値をRefに記録する
  33. 33. RefいわゆるAtomic Object主に以下で構成されている 値の履歴をもつリングバッファ ref-setしたが未コミットのトランザクション Refを参照・更新する際に使われるロック
  34. 34. in-transaction valuesトランザクション内でアクセスしたRefとその値をローカルに記録する Refを更新するときはローカルな値を更新する Refから値を読み出すとき、 ローカルな値があればそれを読み出す なければ、Refの履歴をたどってトランザ クション開始以前の値を読み出す
  35. 35. MVCC多版型同時実行制御 (Multiversion Concurrency Control) トランザクションの実行中、他のトランザクションが既に 更新した値を読み出すと一貫性がなくなる これを防ぐには以下のような方法がある(2つめがMVCC) 他が更新済みの値を読み出そうとした時点でアボート してリトライ 値の履歴をとっておいて、トランザクション開始時ま で って値を読み出す 1つめの方法はリトライの可能性が高くなる
  36. 36. write skew MVCCで起こる現象 複数のトランザクション間で不変条件を破るような変更が行 われたときに発生 不変条件 @a + @b <= 3 Thread A Thread B(dosync (dosync (when (<= (+ @a @b) 2) (when (<= (+ @a @b) 2) (ref-set a (inc a)))) (ref-set b (inc b))))
  37. 37. write skew MVCCで起こる現象 複数のトランザクション間で不変条件を破るような変更が行 われたときに発生 不変条件 @a + @b <= 3 Thread A Thread B(dosync (dosync (when (<= (+ @a @b) 2) (when (<= (+ @a @b) 2) (ref-set a (inc a)))) (ref-set b (inc b))))AとBで違うRefを変更しているので両者ともコミットに成功する コミット後、不変条件は成り立たなくなる
  38. 38. ensure write skewの問題は、暗に存在する「コミットする まで変更されない」という条件が破られるために発 生する Clojureでは (ensure <ref>) で、それ以降コミットが 完了するまで<ref>が変更されないことを保証する Thread A Thread B(dosync (dosync (when (<= (+ @a @b) 2) (when (<= (+ @a @b) 2) (ensure b) (ensure a) (ref-set a (inc a)))) (ref-set b (inc b)))) ensureしているRefが他方に変更されればリトライ
  39. 39. Contention management Thread A Thread B a... @a ... ... (ref-set a ...) ...... (ref-set b ...) ... b ... (ref-set b ...) ... ... (ref-set c ...) ... c
  40. 40. Contention management Thread A Thread B a... @a ... ... (ref-set a ...) ...... (ref-set b ...) ... b ... (ref-set b ...) ... ... (ref-set c ...) ... c 2つのトランザクションが同じRefをつかもうとしたとき、どちら を生かし、どちらをアボートするか?
  41. 41. Contention management Thread A Thread B a... @a ... ... (ref-set a ...) ...... (ref-set b ...) ... b ... (ref-set b ...) ... ... (ref-set c ...) ... c 2つのトランザクションが同じRefをつかもうとしたとき、どちら を生かし、どちらをアボートするか? 戦略次第で性能が大きく左右される
  42. 42. Contention managementの戦略
  43. 43. Contention managementの戦略 Agressive: 相手を殺す
  44. 44. Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ
  45. 45. Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ Karma: あまり仕事をしていない方が死ぬ
  46. 46. Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ Karma: あまり仕事をしていない方が死ぬ Priority: 年功序列。若いやつが死ぬ
  47. 47. Contention managementの戦略 Agressive: 相手を殺す Polite: 自分が死ぬ Karma: あまり仕事をしていない方が死ぬ Priority: 年功序列。若いやつが死ぬClojureのContention managementはPriority+α
  48. 48. まとめロックを使って同期するのは辛いSTM!STM! Clojureなら初心者でもSTM使えますただし、writeが多いと性能低下するなど、問題点もある → 銀の弾丸ではないしかし、将来的にはGCのように適用範囲は広がっていくのでは…?
  49. 49. 参考文献M. Herlihy and N. Shavit. “The Art of Multiprocessor Programming,Revised Reprint.” Morgan Kaufmann Publishers Inc. 2012M. Fogus and C. Houser, “The Joy of Clojure.” Manning Pubns Co.2011Nielsen, Peder RL, and Patrick T. Kristiansen. "BenchmarkingContention Management Strategies in Clojure’s Software." ArtificialIntelligence 8.3 (1977): 323-364.R. Mark Volkmann. “Software Transactional Memory.” http://java.ociweb.com/mark/stm/article.html

×