SlideShare a Scribd company logo
1 of 33
Download to read offline
Immutable List Gem
2014/07/29 KLab 社内勉強会 ALM
細田 翔 (@gam0022)
自己紹介
細田 翔
筑波大学情報学群情報科学類 B4
- 非数値処理アルゴリズム研究室
15卒 KLab内定者
Twitter: @gam0022
http://gam0022.net/
2
話す内容
関数型スタイルでのクイックソートを高速化した話(Ruby)
3
クイックソート
念のためにおさらい
クイックソートの基本的な考え
- データを軸要素(ピボット)より
大きい要素・小さい要素で分割
することを再帰的に繰り返して
ソートを行なう
4
http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/quick-sort.html
Rubyでクイックソート
手続き型スタイルで実装した場合
特徴
1. コードが長い

(tempなどの変数が必要)
2. 昇順降順の切り替えに2箇所の変更
3. 動作が追いにくい
5
OCamlでクイックソート
OCaml (関数型言語)による実装
特徴
1. 5行で書ける!
2. 昇順降順の切り替えは1箇所の変更
3. 動作が追いやすい
6
Ruby vs OCaml
Ruby vs OCaml
- OCaml の圧倒的な勝利
Ruby でも OCaml のよう
なクイックソートを書きたい!
7
Ruby OCaml
行数 29 5
昇順降順の
変更箇所
2 1
可読性 △ ○
Ruby でクイックソート その2
OCaml Ruby
左: OCamlの5行のコードを List.partition を使わないで再実装
右: 左のコードを Ruby に移植したコード
Ruby でも関数型スタイルにプログラミングできた!
8
だが待って欲しい!
Ruby でクイックソートその2
このコードは確かに動作する
問題点
- Array#+ や Array#drop は非破
壊的メソッド
- Array のインスタンスを大量に生成
- Array を何度もコピー
10
処理コストが大きい!
データ構造を見直す
関数型スタイルのプログラミングには、Array(配列)は適さない
データ構造から見なおしてみる
(Immutable) Singly Linked List が最適
- イミュータブルな単方向連結リスト
- OCaml や Lisp の List にも使われる
12
Immutable Singly Linked List を実装
普通に Ruby で実装してもネタとして面白くない
Array は組み込みクラスであり、C言語で実装されているので、
普通にRubyで実装してもパフォーマンス的にも勝ち目がない
「C拡張」として、実装しよう!
13
Ruby の C拡張
C拡張
- C言語で書いたコードをリンクして Ruby から利用する仕組み
部分的な処理の高速化・ラッパーライブラリなどに使われる
例:C拡張を利用した gem
- スクレイピングライブラリの nokogiri
- SQlite3 のラッパーライブラリの sqlite3
14
ImmutableList の実装
クラス名は ImmutableList
struct immutable_list の定義 (Cの構造体をラップ)
15
ImmutableList の実装
OCaml を意識したメソッドを実装
- cons
- head, tail
- rev_append, rev, append
- length
- nth
- inspect
16
ImmutableList の実装
cons (先頭への要素追加) の定義
17
ImmutableList の実装
全部で200行くらいで実装できた
罠が多くて苦労した
- 明示的にオブジェクトをmarkしないと GC で勝手にオブジェ
クトが開放されて SEGV が発生したりとハマりどころが多い
- Ruby 処理系の勉強にはすごくなった
18
Ruby でクイックソート その3
ImmutableList を使用して再実装
19
Ruby でクイックソート 考察
全く同じ処理
クラスを置き換えただけ
性能に違いが出るか?
20
Array ImmutableList
Array ImmutableList
first head
drop(1) tail
[i]+a a.cons(i)
ベンチマーク
データの長さn と 処理時間(CPU時間) の関係を調査
ソートデータ: 重複のないランダムなデータを使用
最新の Ruby 2.1.2 を使用
21
結果
22
リストの長さのクイックソートの実行時間
実行時間[sec]
0
0.1
0.2
0.3
0.4
リストの長さ[個]
0 2000 4000 6000 8000
Array ImmutableList
リストの長さに比例して、ImmutableList が高速になる
最大で4.3倍の高速化!
まとめ
処理によっては、再帰を用いた関数型スタイルでプログラミン
グすることで、シンプルに実装できる場合がある
パフォーマンス的には、Ruby の Array は関数型スタイルには
適していない
C拡張として実装した ImmutableList によって、関数型スタ
イルでのクイックソートを高速化することができた!
23
RubyGems に公開中
RubyGems は Ruby ライブラリの管理システム
immutable_list の名前で登録済みなので、コマンド一発で導入可能
24
ご静聴ありがとうございました
おまけ
本当にC拡張で作った意味があったので疑問だったので、Ruby
でも同じ機能を持つクラスを実装した
ソースコードはC実装の1/3くらいになった(Rubyの生産性す
ごい)
次のベンチマークをとった
- 先ほどのクイックソート
- 単純な連結(append)処理
26
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拡張版の方が少し高速
ImmutableListのRuby実装と比較
連結の回数と実行時間(対数グラフ)
実行時間[sec]
0.01
0.1
1
10
100
連結回数[回]
1000 10000 100000
Array ImmutableList
ImmutableList(Ruby)
長さ6のリストをn回連結
28
ImmutableListのRuby実装と比較
C拡張版の方が高速で良かった
でも、思ったよりは変わらなくて残念(́・ω・`)
関数型スタイルは手続き型スタイルよりすごく遅い
29
Immutable List が Array より

メモリの消費が少ない説明
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
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
head と tail
次の操作は参照を返すだけなので、とても高速
- head: 先頭の要素の取り出し Array#first に対応
- tail: 2番目以降のリストの取り出し Array#drop に対応
33
1 2 3 4 5 6 7 8
tail
head

More Related Content

What's hot

PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法
Yosuke Onoue
 

What's hot (9)

Lispmeetup #45 Common Lispで音声合成
Lispmeetup #45 Common Lispで音声合成Lispmeetup #45 Common Lispで音声合成
Lispmeetup #45 Common Lispで音声合成
 
ICFP2009-いかにして我々は戦ったか
ICFP2009-いかにして我々は戦ったかICFP2009-いかにして我々は戦ったか
ICFP2009-いかにして我々は戦ったか
 
深層学習フレームワーク Chainerとその進化
深層学習フレームワークChainerとその進化深層学習フレームワークChainerとその進化
深層学習フレームワーク Chainerとその進化
 
CuPy解説
CuPy解説CuPy解説
CuPy解説
 
Chainer入門と最近の機能
Chainer入門と最近の機能Chainer入門と最近の機能
Chainer入門と最近の機能
 
Chainer Meetup LT (Alpaca)
Chainer Meetup LT (Alpaca)Chainer Meetup LT (Alpaca)
Chainer Meetup LT (Alpaca)
 
PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法
 
LT@Chainer Meetup
LT@Chainer MeetupLT@Chainer Meetup
LT@Chainer Meetup
 
Numpy scipy matplotlibの紹介
Numpy scipy matplotlibの紹介Numpy scipy matplotlibの紹介
Numpy scipy matplotlibの紹介
 

Similar to Immutable List Gem (KLab ALM版) (6)

アプリケーション開発における暗号化
アプリケーション開発における暗号化アプリケーション開発における暗号化
アプリケーション開発における暗号化
 
Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crf
 
CSPによる並行システムの検証(2)
CSPによる並行システムの検証(2)CSPによる並行システムの検証(2)
CSPによる並行システムの検証(2)
 
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
 
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会
.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会.NET micro  FrameWork for TOPPERS  (.NET基礎)@基礎勉強会
.NET micro FrameWork for TOPPERS (.NET基礎)@基礎勉強会
 
Rubyと機械学習の現状
Rubyと機械学習の現状Rubyと機械学習の現状
Rubyと機械学習の現状
 

More from Sho Hosoda

More from Sho Hosoda (8)

Hanamaru Renderer for レイトレ合宿5‽
Hanamaru Renderer for レイトレ合宿5‽Hanamaru Renderer for レイトレ合宿5‽
Hanamaru Renderer for レイトレ合宿5‽
 
シェーダだけで世界を創る!three.jsによるレイマーチング
シェーダだけで世界を創る!three.jsによるレイマーチングシェーダだけで世界を創る!three.jsによるレイマーチング
シェーダだけで世界を創る!three.jsによるレイマーチング
 
three.js の紹介
three.js の紹介three.js の紹介
three.js の紹介
 
カメラで商品検索
カメラで商品検索カメラで商品検索
カメラで商品検索
 
TwinCal(学生のためのアプリ開発コンテストVer.)
TwinCal(学生のためのアプリ開発コンテストVer.)TwinCal(学生のためのアプリ開発コンテストVer.)
TwinCal(学生のためのアプリ開発コンテストVer.)
 
Rubyで連結リスト使うためのgemを作った(tsukuba.rb版)
Rubyで連結リスト使うためのgemを作った(tsukuba.rb版)Rubyで連結リスト使うためのgemを作った(tsukuba.rb版)
Rubyで連結リスト使うためのgemを作った(tsukuba.rb版)
 
Twincal
TwincalTwincal
Twincal
 
Twitter名刺ジェネレータ
Twitter名刺ジェネレータTwitter名刺ジェネレータ
Twitter名刺ジェネレータ
 

Immutable List Gem (KLab ALM版)