Successfully reported this slideshow.
Your SlideShare is downloading. ×

Immutable List Gem (KLab ALM版)

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 33 Ad
Advertisement

More Related Content

Advertisement
Advertisement

Recently uploaded (20)

Immutable List Gem (KLab ALM版)

  1. 1. Immutable List Gem 2014/07/29 KLab 社内勉強会 ALM 細田 翔 (@gam0022)
  2. 2. 自己紹介 細田 翔 筑波大学情報学群情報科学類 B4 - 非数値処理アルゴリズム研究室 15卒 KLab内定者 Twitter: @gam0022 http://gam0022.net/ 2
  3. 3. 話す内容 関数型スタイルでのクイックソートを高速化した話(Ruby) 3
  4. 4. クイックソート 念のためにおさらい クイックソートの基本的な考え - データを軸要素(ピボット)より 大きい要素・小さい要素で分割 することを再帰的に繰り返して ソートを行なう 4 http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/quick-sort.html
  5. 5. Rubyでクイックソート 手続き型スタイルで実装した場合 特徴 1. コードが長い
 (tempなどの変数が必要) 2. 昇順降順の切り替えに2箇所の変更 3. 動作が追いにくい 5
  6. 6. OCamlでクイックソート OCaml (関数型言語)による実装 特徴 1. 5行で書ける! 2. 昇順降順の切り替えは1箇所の変更 3. 動作が追いやすい 6
  7. 7. Ruby vs OCaml Ruby vs OCaml - OCaml の圧倒的な勝利 Ruby でも OCaml のよう なクイックソートを書きたい! 7 Ruby OCaml 行数 29 5 昇順降順の 変更箇所 2 1 可読性 △ ○
  8. 8. Ruby でクイックソート その2 OCaml Ruby 左: OCamlの5行のコードを List.partition を使わないで再実装 右: 左のコードを Ruby に移植したコード Ruby でも関数型スタイルにプログラミングできた! 8
  9. 9. だが待って欲しい!
  10. 10. Ruby でクイックソートその2 このコードは確かに動作する 問題点 - Array#+ や Array#drop は非破 壊的メソッド - Array のインスタンスを大量に生成 - Array を何度もコピー 10
  11. 11. 処理コストが大きい!
  12. 12. データ構造を見直す 関数型スタイルのプログラミングには、Array(配列)は適さない データ構造から見なおしてみる (Immutable) Singly Linked List が最適 - イミュータブルな単方向連結リスト - OCaml や Lisp の List にも使われる 12
  13. 13. Immutable Singly Linked List を実装 普通に Ruby で実装してもネタとして面白くない Array は組み込みクラスであり、C言語で実装されているので、 普通にRubyで実装してもパフォーマンス的にも勝ち目がない 「C拡張」として、実装しよう! 13
  14. 14. Ruby の C拡張 C拡張 - C言語で書いたコードをリンクして Ruby から利用する仕組み 部分的な処理の高速化・ラッパーライブラリなどに使われる 例:C拡張を利用した gem - スクレイピングライブラリの nokogiri - SQlite3 のラッパーライブラリの sqlite3 14
  15. 15. ImmutableList の実装 クラス名は ImmutableList struct immutable_list の定義 (Cの構造体をラップ) 15
  16. 16. ImmutableList の実装 OCaml を意識したメソッドを実装 - cons - head, tail - rev_append, rev, append - length - nth - inspect 16
  17. 17. ImmutableList の実装 cons (先頭への要素追加) の定義 17
  18. 18. ImmutableList の実装 全部で200行くらいで実装できた 罠が多くて苦労した - 明示的にオブジェクトをmarkしないと GC で勝手にオブジェ クトが開放されて SEGV が発生したりとハマりどころが多い - Ruby 処理系の勉強にはすごくなった 18
  19. 19. Ruby でクイックソート その3 ImmutableList を使用して再実装 19
  20. 20. Ruby でクイックソート 考察 全く同じ処理 クラスを置き換えただけ 性能に違いが出るか? 20 Array ImmutableList Array ImmutableList first head drop(1) tail [i]+a a.cons(i)
  21. 21. ベンチマーク データの長さn と 処理時間(CPU時間) の関係を調査 ソートデータ: 重複のないランダムなデータを使用 最新の Ruby 2.1.2 を使用 21
  22. 22. 結果 22 リストの長さのクイックソートの実行時間 実行時間[sec] 0 0.1 0.2 0.3 0.4 リストの長さ[個] 0 2000 4000 6000 8000 Array ImmutableList リストの長さに比例して、ImmutableList が高速になる 最大で4.3倍の高速化!
  23. 23. まとめ 処理によっては、再帰を用いた関数型スタイルでプログラミン グすることで、シンプルに実装できる場合がある パフォーマンス的には、Ruby の Array は関数型スタイルには 適していない C拡張として実装した ImmutableList によって、関数型スタ イルでのクイックソートを高速化することができた! 23
  24. 24. RubyGems に公開中 RubyGems は Ruby ライブラリの管理システム immutable_list の名前で登録済みなので、コマンド一発で導入可能 24
  25. 25. ご静聴ありがとうございました
  26. 26. おまけ 本当にC拡張で作った意味があったので疑問だったので、Ruby でも同じ機能を持つクラスを実装した ソースコードはC実装の1/3くらいになった(Rubyの生産性す ごい) 次のベンチマークをとった - 先ほどのクイックソート - 単純な連結(append)処理 26
  27. 27. ImmutableListのRuby実装と比較 Ruby で実装した ImmutableList(Ruby) 手続き型スタイルのクイックソート Procedural 27 リストの長さとクイックソートの実行時間 実行時間[sec] 0 0.1 0.2 0.3 0.4 リストの長さ[個] 0 2000 4000 6000 8000 Array ImmutableList ImmutableList(Ruby) Procedural C拡張版の方が少し高速
  28. 28. ImmutableListのRuby実装と比較 連結の回数と実行時間(対数グラフ) 実行時間[sec] 0.01 0.1 1 10 100 連結回数[回] 1000 10000 100000 Array ImmutableList ImmutableList(Ruby) 長さ6のリストをn回連結 28
  29. 29. ImmutableListのRuby実装と比較 C拡張版の方が高速で良かった でも、思ったよりは変わらなくて残念(́・ω・`) 関数型スタイルは手続き型スタイルよりすごく遅い 29
  30. 30. Immutable List が Array より
 メモリの消費が少ない説明
  31. 31. Arrayの連結 C = A+B を行なった時、AとBの内容を全てコピーする 1 2 3 4 5 6 7 8+ A B 1 2 3 4 5 6 7 8 A B 1 2 3 4 5 6 7 8 C
  32. 32. Immutable Singly Linked List の連結 C = A+B を行なった時、Bとの差分だけがコピーされる 1 2 3 4 5 6 7 8+ A B 1 2 3 A 1 2 3 C 4 5 6 7 8 B
  33. 33. head と tail 次の操作は参照を返すだけなので、とても高速 - head: 先頭の要素の取り出し Array#first に対応 - tail: 2番目以降のリストの取り出し Array#drop に対応 33 1 2 3 4 5 6 7 8 tail head

×