密な演算子呼び出しで実現した 内部DSLの前処理による 実行速度改善の試み 東京大学 情報理工学系研究科 長田朋久 千葉滋 Osada Tomohisa 1 内部DSL (Domain Specific Languages) • 特定の領域に特化したプログラミング言語の ライブラリ • 自然な表記が可能 – 例: ScalaのList val lst = 1 :: 2 :: 3 :: Nil Osada Tomohisa 2 内部DSL (Domain Specific Languages) • 特定の領域に特化したプログラミング言語の ライブラリ • 自然な表記が可能 – 例: ScalaのList val lst = ((Nil.::(3)).::(2)).::(1) "::" はListクラスのメソッド 組み込み演算子ではない • ホスト言語の文法的制約を受ける Osada Tomohisa 3 密な演算子呼び出しによる内部DSL • Scala 1.+(2) = 1 + 2 – 二項演算子に見えるメソッドを定義可能 – ドットと括弧を省略できるが空白が必要 – 可能な演算子名に制限がある • メソッド名であるため • ProteaJ [Ichikawa et al, Modluarity'14] – n項演算子を定義可能, 空白不要, メソッド名に 制限がない – 擬似的なリテラルを演算子で定義可能 • 密な演算子呼び出しになりやすい Osada Tomohisa 4 擬似的なリテラルを密な演算子呼び出しで 表現する 0b101 // 5 "0b" _ : Binary -> Int "0" "1" "0" "1" Osada Tomohisa _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 5 擬似的なリテラルを密な演算子呼び出しで 表現する オペレータ 0b101 // 5 単項演算子 オペランド "0b" _ : Binary -> Int "0" "1" "0" "1" _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 無項演算子 (関数)型 Osada Tomohisa 6 擬似的なリテラルを密な演算子呼び出しで 表現する Expect Binary value Return Int value 0b101 // 5 "0b" _ : Binary -> Int "0" "1" "0" "1" Osada Tomohisa _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 7 擬似的なリテラルを密な演算子呼び出しで 表現する Expect Binary value Return Int value 0b101 // 5 0b "0b" _ : Binary -> Int "0" "1" "0" "1" Osada Tomohisa _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 8 擬似的なリテラルを密な演算子呼び出しで 表現する Expect Binary value Return Int value 0b101 // 5 0b 1 "0b" _ : Binary -> Int "0" "1" "0" "1" Osada Tomohisa _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 9 擬似的なリテラルを密な演算子呼び出しで 表現する Expect Binary value Return Int value 0b101 // 5 0b 1 0 "0b" _ : Binary -> Int "0" "1" "0" "1" Osada Tomohisa _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 10 擬似的なリテラルを密な演算子呼び出しで 表現する Expect Binary value Return Int value 0b101 // 5 0b 1 0 1 "0b" _ : Binary -> Int "0" "1" "0" "1" _ : Binary -> Binary _ : Binary -> Binary : Binary : Binary 4回の演算子呼び出しが密に発 生 Osada Tomohisa 11 密な演算子呼び出しによる実行時間の低速化 • 独自に作成した言語にて実験 • 2進数リテラルの評価時間を 計測 350 300 time[ms] – "0b10101" を4万回評価 400 250 200 • 通常のリテラル 150 100 – コンパイル時に意味解析 50 • 密な演算子呼び出し 0 – 遅い. 実行時に意味解析(=演算子実行) mean しているようなもの evaluation time Osada Tomohisa dense operator calls native literals 14 密な演算子呼び出し部分の構文木変換 • 目標 – 密な演算子呼び出しによる内部DSLの実行時間を 削減する • 方法 – 内部DSL使用部分の構文木をコンパイル時に 前処理で変換する • 同一内部DSLの命令は一箇所にまとまって 存在する Osada Tomohisa 15 実験に用いた独自言語 • 密な演算子呼び出しによる内部DSLを 構成可能な言語を作成 operators TupleInt { "0" () = 0 -> 1; "1" () = 1 -> 1; [r] "0" _ (TupleInt pair) = (first pair) -> ((second pair) + 1); [r] "1" _ (TupleInt pair) = ((first pair) + (1 << (second pair))) -> ((second pair) + 1); }; operators Int { [r] "0b" _ (TupleInt pair) = first pair; }; Osada Tomohisa 16 実装した構文木の変換 • まず, 演算子のインライン展開を実装した – 例: 0b10 のインライン展開 Call Call(Var("0b"), Call(Var("1"), Call(Var("0"),Tuple(0,1)))) Var Call Var Call Var Tuple 構文木の文字列表現 First(Tuple(Plus(First(Tuple(0,1)), LeftShift(1,Second(Tuple(0,1)))), Plus(Second(Tuple(0,1)),1))) Osada Tomohisa 17 インライン展開実装版の実行時間 • 独自に作成した言語にて実験 • 2進数リテラルの実行時間を 計測 – インライン展開により大幅に 速度が低下した • 理由は調査中 2000 time[ms] – "0b10101" を4万回評価 2500 dense operator calls 1500 native literals 1000 500 inlining 0 mean evaluation time Osada Tomohisa 18 関連研究 • 書き換え規則 – CodeBoost (C++): • http://codeboost.org/ – GHC/Haskell rewrite rules (Haskell): • https://downloads.haskell.org/~ghc/7.0.1/docs/html/u sers_guide/rewrite-rules.html {-# RULES "map/map" forall f g xs. map f (map g xs) = map (f.g) xs #-} Osada Tomohisa 19 今後の予定 • 具体的な前処理の内容を考案する – 特定のDSLに特化した構文木の変換 • 実用的な言語で実装する – Java(ProteaJ)上 Osada Tomohisa 20
© Copyright 2024 ExpyDoc