Post on 24-May-2015
description
関数型 LT大会
Unboxed objects and polymorphic typing
nomaddo@no maddo
東北大学大学院 情報科学研究科
2014年 5月 11日
Who am I?
@no maddoOCaml, SML#, EmacsHaskellは分かりません…。
• 東北大学の大学院生 (M1)
• 論理学とか型理論とかコンパイラとか勉強してます• 趣味は list-packageで拡張プラグインのリストを眺めること• 艦これでなら山城・扶桑が好きです• インターン先を探しています!
2 / 37
東北大ってどんなとこ?
A.山です
• 熊が出る• 熊に注意しろとメールが来る
• 大学生協で熊よけの鈴が売っていた
• 教員もネタにする
3 / 37
東北大ってどんなとこ?A.山です
• 熊が出る• 熊に注意しろとメールが来る
• 大学生協で熊よけの鈴が売っていた
• 教員もネタにする
3 / 37
東北大ってどんなとこ?A.山です
• 熊が出る• 熊に注意しろとメールが来る
• 大学生協で熊よけの鈴が売っていた
• 教員もネタにする
3 / 37
東北大ってどんなとこ?A.山です
• 熊が出る• 熊に注意しろとメールが来る
• 大学生協で熊よけの鈴が売っていた
• 教員もネタにする
3 / 37
本日話すこと
• 論文紹介Unboxed objects and polymorphic typingXavier Leroy (POPL92)
http://gallium.inria.fr/~xleroy/publi/
unboxed-polymorphism.pdf
みなさん単純型付きラムダ計算くらいわかりますよね…???• 私の研究のことPPL2014のポスター発表「OCamlにおける多相関数の複製の実験」と思ったんですけど時間ないのでやりません (・́ω・` )
4 / 37
論文紹介アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
5 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
6 / 37
静的型付けとデータ表現静的型付き言語では、型情報を利用してよりよりデータ表現を選ぶことが出来る
• 動的型付き言語では、値は uniformに表現するしか無い• このような言語では 1ワードで表現できないデータは Box化して 1ワードにする必要がある
• Cのような静的型付き言語では事前に値の型がわかっているので、その値の長さもわかる。
• データの表現を効率的なものにすることが出来る
box化ヒープにアロケートしてポインタとして扱うこと
uniform representatin
値を box化して、すべての値を1ワードで表すこと
7 / 37
polymorphismの問題点
• 静的な型情報をコンパイルに利用するためには全ての値にはユニークな型がついていなければならない
• しかし、polymorphismを扱う言語ではこれは成り立たない。
(* int -> int. i n t型の値のサイズは 1ワード *)
let succ x = x + 1
(* ’a -> ’a. ’ a型の値のサイズは分からない *)
let id x = x
これをどうやってコンパイルすればよいだろうか。
8 / 37
解決策
コンパイルの先送りAdaの genericの実装で使われている解決方法多相的な objectは使われるまでコンパイルを先送りするデータ表現は効率的だが、コード複製をしないといけないし、分割コンパイルできなくなる!(いまでいう C++のテンプレートの解決策)
全ての表現をBox化する多くのML系言語の処理系で採用されている解決方法シリアスに効率を損なう!例えば tupleは常にヒープにアロケートしないといけない
9 / 37
本論文の提案: Mixed Representation
本論文では、他の解決手段を提案する。• 単相的な値はそれぞれの Specialized Representationを用いる(データ型各々のサイズの表現を用いる)
• 多相的な値は box化して uniformに表現する
先行研究として [PeytonJones 91]では同様の表現を形式化している本論文では PeytonJones’ representatin への変換方法や実際のコンパイラでのベンチマーク結果について報告している
10 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事関数の変換の具体例
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
11 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事関数の変換の具体例
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
12 / 37
やりたい変換の例1
まず、簡単な例から見てみる。let make_pair = λx.(x, x) (∗ ∀α. α→ α ∗ α ∗)
makepair(3.14) という関数適用を考えてみると、
• 多相的な部分にくる値は box化しているとする• そのままmakepairに 3.14を渡すことは出来ない(makepairの α型の引数は box化されていることを仮定する)
• 返り値にはフラットな、box化されてない pairを返してほしい• 値を box化したりする、変換が必要なことがわかる
wrap(τ), unwrap(τ)という 2つのオペレータを導入すると、
let x = makepair(wrap(float )(3.14)) in
(unwrap(float)(fst(x)), unwrap(float)(snd(x)))
13 / 37
やりたい変換の例2(* map_pair : ∀α, β. (α→ β)→ α× α→ β × β *)
let map pair =λ f. λ x. (f(fst(x), f(snd(x))))
let int pair = map pair int of float (3.14, 2.718)
変換後let int pair =
let y = map pair(λ x. wrap(int) (int of float (unwrap(float)(x))))(wrap(float)(3.14), wrap(float)(2.718))
in (unwrap(int)(fst(y)), unwrap(int)(snd(y)))
多相的な値は box化されていることに注意。多相関数の呼び出し側で unboxしてやる。
14 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
15 / 37
Formalization
この章で扱うことは下の通り。残念ですが時間がないので飛ばします!!!• 変換前と変換後の言語の定義• 言語の変換規則• 変換しても型がつくこと• 変換してもプログラムの意味が失われないこと
16 / 37
扱う言語の定義
単純型付きラムダ計算に型スキーム、let構文を追加した言語
• aは source language, a’は target language
• iは intの値、fは floatの値• τ は型、σ は 型スキーム• Gen(τ, E) は τ の自由な変数を ∀で束縛した型スキーム
17 / 37
型付け規則
18 / 37
型付けの例E ′ = E + x : αE ′′ = E + id : ∀α.α→ αρ = α← int
(E + x : α)(x) = α Dom(∅) ⊆ ∅E + x : α ⊢ x : αE ⊢ λx.x : α→ α
E′′(id) = ∀α.α→ α Dom(ρ) ⊆ {α}E′′ ⊢ id : ρ(α→ α) = int→ int E′′ ⊢ 14 : int
E′′ = E + id : ∀α.α→ α ⊢ id 14 : int
E ⊢ λx.x : α→ α E + id : Gen(α→ α,E) ⊢ id 14 : int
E ⊢ let id = λx.x in id 14 : int
19 / 37
変換規則1
型を拡張しますτ ′ ::= α | int | float | τ1′ → τ2′ | τ1′ ∗ τ2′ | [τ ′][τ ′]は wrapされた値の型E ⊢ a : τ => a′ で aに τ 型がつくとき、 項 aは a’に変換できる
20 / 37
変換規則2Gρと SρはDualですねー
21 / 37
示したいこと1:変換しても型がつく!
ただし、target languageの型付け規則に以下を加える
22 / 37
操作的意味論の定義1
syntaxを定義したらそりゃsemanticsも定義しますよね?まずは valueの定義…v ::= i|f | < v > |v1, v2|clos(k, λx.a, e)|opop ::= add|...
23 / 37
操作的意味論の定義2
24 / 37
25 / 37
示したいこと:2つの言語の意味が一緒
26 / 37
equalityの定義もとの言語と変換後の言語の等しさ!
27 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
28 / 37
しんどい話1
MLではユーザが新しい型を作ることが出来るもうちょっと複雑なデータ構造の議論をする相変わらず List, Arrayは Flatにできない!!!
(* list の 定 義 *)
datatype ’a list = Nil | Cons of ’a * ’a list
fun length Nil = 0 (* length : ’a list -> int *)
| length (Cons e, l) = 1 + length l
Cons(3.14, Nil) はフラットに扱えれば空間効率よさそうしかし length関数にこのリストを渡すことを考えるとまずい
29 / 37
しんどい話2
• length: ’a list → int の’aに代入される型のサイズは不明• 最初の make_pairの例では α ∗ α型の値から fst,sndで値を取り出してもう一度 pairを作っている
• Listも’a listを引数にとる多相関数に渡すときに、作りなおせば良い?⇒ 作り直すのは時間的にも空間的にもコストが重い…Listのような構造は flatにできない…。つらい。つらい。
Table : flat list
Table : a little nested list
30 / 37
しんどい話3
• 今度は α ∗ α list → ... という関数を考えてみる• float ∗ float list を渡すことを考える。なるべく tupleもフラットにしたいが、関数が要求する形は下の通り
• このケースでは tupleも作り直すのではなく box化してしまったほうが良い?
31 / 37
アウトライン
1 polymorphicな値をコンパイルする難しさ
2 本論文でやりたい事
3 Formalization
4 Concrete data types
5 MLの実装とベンチマーク結果
32 / 37
Galliumコンパイラの実装1
Mixed representationを採用したコンパイラを実装その仕様について述べていく• unwraped integerは unboxedな 32bit長のデータ、wrapしても 1ワードで済むが GCのため box化
• 8bit整数が char, boolean, enumのために存在wrapされても unboxedのまま
• unitは 0個要素のタプルで warpされた unitは特別な定数• closureは 2ワード長の wrapされてない表現として扱う(実行コード列へのポインタと、環境へのポインタ)
• Arrayの要素は全て wrapされている• tupleは要素が 4つ以上のときは unboxedでは扱わない• ユーザー定義のデータ構造は前に議論したように扱う
33 / 37
Galliumコンパイラの実装2
細かい話が多いので、大切そうな部分だけ書きます
• Gallium compilerのバックエンドは C--C--は Cから structと union抜いて GCと例外をサポート
• オリジナルの部分は、タグ無しの値がポインタかそれ以外か区別するために、型情報を用いること(古典的 GCはタグによりポインタかそれ以外か区別する)
34 / 37
ベンチマーク結果1
Gallium0は Galliumとバックエンド・コードジェネレータを共有してるが古典的な boxed data representatinを採用している
35 / 37
ベンチマーク結果2
• test1, 2は数値計算でUnboxedな intと floatの効果が現れている• 5,6,8でも box化されない表現のメリットを享受できている
• これらは要素が全て box化される構造にアクセスするテスト
• 値の受け渡しに unboxed tuple, closureを扱えた影響では• test7の話
• 多相的で高階な関数を多用した場合、uniformな表現のほうが効率が良い
• 変換コードが沢山挿入されるため、 test7は露骨にその影響が出ている
• test7は int listを quad quad (λx.x+ 1), quad =λf.λx.f(fx)でマップするテスト
36 / 37
まとめ
• 静的な型情報をコンパイルに活用し、なるべく unboxedな表現を用いるシンプルな方法を提案
• それでも listや arrayの要素は box化せざるを得ないが、unboxedな tuple、closureなどの有用性を確認した
• 数値計算では目覚ましく効率が向上し、高階関数を多く使うときには効率が悪い事がわかった
• 単純型付きラムダ計算+ let多相が分かると論文読めます!!!!• 論文読むの楽しい!!!(’ω’ )三 (’ω’) 三 ( ’ω’)
37 / 37