Mercurial > hg > Papers > 2014 > kaito_sigos
changeset 20:9154e714658d
replace 。/、 with ./,
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Apr 2014 19:00:46 +0900 |
parents | 1a6b5fb7a8d9 |
children | 4025f8246a05 |
files | 2014_sigos.tex |
diffstat | 1 files changed, 28 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/2014_sigos.tex Tue Apr 22 18:57:44 2014 +0900 +++ b/2014_sigos.tex Tue Apr 22 19:00:46 2014 +0900 @@ -6,7 +6,6 @@ \usepackage{slashbox} %% tabularでの斜め線 \usepackage{listings} %\usepackage{jtygm} -%\usepackage{mediabb} \usepackage{float} \lstset{ language={C}, @@ -112,41 +111,40 @@ % 全体的に冗長な表現が多いので、もっと削って。 \section{Continuation based C on LLVM} -当研究室では, プログラムを code segment, data segment という単位を用いて書くという手法を提案している. この手法を用いてプログラミングを行う言語として Continuation based C (以下CbC) というプログラミング言語を開発しており, これは C の下位の言語にあたる. CbC においてコードセグメント間の処理の移動は goto 文を用いた軽量継続によって行われる。 -% これは Tail Call Elimination というコンパイラの持つ最適化の強制によって実現される. -CbC の goto 文はハードウェア記述のような状態遷移ベースのプログラミングを行うのに適しており, プログラム生成のターゲットとして優れている。例えば、正規表現検査器を -状態遷移系に変換する場合にはアセンブラやLLVMなどの中間コードよりもポータブルかつ読みやすい形で生成することができる。 -CbC では呼び出し前の code segment に戻るための環境がないので、スレッドのコンテキストスイッチを容易に実装することができる. +当研究室では, プログラムを code segment, data segment という単位を用いて書くという手法を提案している. この手法を用いてプログラミングを行う言語として Continuation based C (以下CbC) というプログラミング言語を開発しており, これは C の下位の言語にあたる. CbC においてコードセグメント間の処理の移動は goto 文を用いた軽量継続によって行われる. +CbC の goto 文はハードウェア記述のような状態遷移ベースのプログラミングを行うのに適しており, プログラム生成のターゲットとして優れている. 例えば, 正規表現検査器を +状態遷移系に変換する場合にはアセンブラやLLVMなどの中間コードよりもポータブルかつ読みやすい形で生成することができる. +CbC では呼び出し前の code segment に戻るための環境がないので, スレッドのコンテキストスイッチを容易に実装することができる. これにより OpenCL, CUDA, そして Cerium といった並列開発環境を用いたプログラムの記述に向いている. また, meta code segment, meta data segment といったメタレベルの単位を用意することで柔軟なメタプログラミングが可能になる. これまでに開発された CbC のコンパイラは Micro-C をベースにしたものと GCC をベースにしたものの二種がある. -CbC での goto 文を実装するには、末尾最適化を利用することができる。実際に、GCC の中間コードやコード生成器を最小限に変更し、 -最適化と干渉することなく CbC 言語を実現することが可能なことを示した\cite{}。 +CbC での goto 文を実装するには, 末尾最適化を利用することができる. 実際に, GCC の中間コードやコード生成器を最小限に変更し, +最適化と干渉することなく CbC 言語を実現することが可能なことを示した\cite{}. -今回、広く使われるようになってきたLLVM 上に CbC を実装した。LLVM はGCCと異なり中間コードを生成する clang と、中間コードを -アセンブラに変化する llvm の二つのプログラムに完全に分かれている。中間コードには、大域Jump に相当するコードがないので、 -GCC と同じ方法では実装することはできない。また、GCC で CbC の code segment からCに戻る時に使う環境付き goto を実現するのに -用いた nested function は LLVM には存在しない。 +今回, 広く使われるようになってきたLLVM 上に CbC を実装した. LLVM はGCCと異なり中間コードを生成する clang と, 中間コードを +アセンブラに変化する llvm の二つのプログラムに完全に分かれている. 中間コードには, 大域Jump に相当するコードがないので, +GCC と同じ方法では実装することはできない. また, GCC で CbC の code segment からCに戻る時に使う環境付き goto を実現するのに +用いた nested function は LLVM には存在しない. -中間コードではCALLやRETURNは、そのままで、CALLに存在する末尾最適化フラグを利用することで code segment であることを表す。 -このフラグは、 Haskell や Erlang あるいは Scheme など、末尾最適化が言語仕様に含まれるものに対して用意されている。 -なので、LLVMの 中間コード自体の変更は不要であることがわかった。llvm 側では、フラグに沿って末尾最適化の強制を行う。これにより、LLVM の最適化と -さまざまなアーキテクチャのコード生成に干渉することなく CbC を実現できた。 +中間コードではCALLやRETURNは, そのままで, CALLに存在する末尾最適化フラグを利用することで code segment であることを表す. +このフラグは, Haskell や Erlang あるいは Scheme など, 末尾最適化が言語仕様に含まれるものに対して用意されている. +なので, LLVMの 中間コード自体の変更は不要であることがわかった. llvm 側では, フラグに沿って末尾最適化の強制を行う. これにより, LLVM の最適化と +さまざまなアーキテクチャのコード生成に干渉することなく CbC を実現できた. -LLVM や最近のGCCでは最適化を関数展開に頼っており、それを禁止すると生成されるコードの質が低下する。CbC では goto は -単一の jmp 命令になるので、相対的に関数展開の重要性が低下する。実装したLLVMのコードは十分な性能を持つが、GCCよりは -若干性能が落ちている。GCC では末尾最適化は最適化レベル2でのみ行われるので、デバッガなどが有効になる -最適化レベル0では CbC を実行することはできない。今回作成した LLVM 版では、最適化レベル0でも末尾最適化を矯正できるので、 -デバッガなどを適切に使うことができる。 +LLVM や最近のGCCでは最適化を関数展開に頼っており, それを禁止すると生成されるコードの質が低下する. CbC では goto は +単一の jmp 命令になるので, 相対的に関数展開の重要性が低下する. 実装したLLVMのコードは十分な性能を持つが, GCCよりは +若干性能が落ちている. GCC では末尾最適化は最適化レベル2でのみ行われるので, デバッガなどが有効になる +最適化レベル0では CbC を実行することはできない. 今回作成した LLVM 版では, 最適化レベル0でも末尾最適化を矯正できるので, +デバッガなどを適切に使うことができる. \section{CbCの例題} CbC では C の関数の代わりに code segment を用いて処理を記述し, code segment 間の移動に goto を用いる. -構文は それ以外はC と同じである。通常のC の関数をそのまま使用することもできる。 -必要であれば、関数呼び出しは goto を用いた継続に, ループ制御を再帰的な継続に置き換えて、 -goto のみのプログラムに変換することも可能である。本論文で用いる例題conv1は、そのような -変換の例になっている。 +構文は それ以外はC と同じである. 通常のC の関数をそのまま使用することもできる. +必要であれば, 関数呼び出しは goto を用いた継続に, ループ制御を再帰的な継続に置き換えて, +goto のみのプログラムに変換することも可能である. 本論文で用いる例題conv1は, そのような +変換の例になっている. code segment の記述は C の関数の構文と同じで, 型に \_\_code を使うことで宣言でき, code segment 間の移動は goto の後に code segment 名と引数を並べて記述することで行える. この goto による処理の遷移を継続と呼ぶ. @@ -400,13 +398,13 @@ GCC 上に実装した CbC コンパイラでは nested function を用いていた\cite{yogi:2008a}が, LLVM/clang ではこの拡張構文は対応しておらず, 別の方法をとる必要がある. そこで今回の実装には setjmp, longjmp を用いた実装を行った. \_\_return, \_\_environment が宣言されると, 環境付き継続を用いる関数内での継続前に setjmp の構文が追加され, 環境を保持して継続を行うようになる. このとき, \_\_return には元の環境に戻るための code segment へのアドレスが, \_\_environment には元の環境が保持され, \_\_return の指す code segment に \_\_environment を渡して継続することで元の環境に戻ることができる. \_\_return へ継続することで元の環境に戻ることができるのは \_\_return の指す code segment が longjmp を呼び出すためである. また, 環境付き継続を行う際には戻り値を返すために継続元の関数の型をコピーしなければならないという問題があるが, clang では \ref{sec:QualType}節で述べた QualType をコピーするだけで解決する. -setjmp/longjmp を使って C の関数に戻ることは CbC コンパイラとは関係なくプログラムレベルでも実現できる。しかし、本来は取っておいた C のstack pointerを回復するだけでよく、 -register のsaveなどを伴う比較的重い作業である setjmp は必要ないはずである。Micro C 実装ではそのように実装されている。 -将来的により軽い処理で戻れる構文を維持することが望ましいと考えられるので、LLVM/GCC 内部で、Cへの復帰のコードを提供するようにしている。 +setjmp/longjmp を使って C の関数に戻ることは CbC コンパイラとは関係なくプログラムレベルでも実現できる. しかし, 本来は取っておいた C のstack pointerを回復するだけでよく, +register のsaveなどを伴う比較的重い作業である setjmp は必要ないはずである. Micro C 実装ではそのように実装されている. +将来的により軽い処理で戻れる構文を維持することが望ましいと考えられるので, LLVM/GCC 内部で, Cへの復帰のコードを提供するようにしている. \section{評価と考察} 評価は, コンパイルして出力されたアセンブリコードの確認と, CbC プログラムを Micro-C, GCC, LLVM/clang でコンパイルして得られたプログラムの実行速度を計測により行う. コンパイル, 計測は x86-64 アーキテクチャの Mac OS X 上で行った. なお, このときの GCC のバージョンは 4.9.0 である. -末尾最適化が行われない場合は、警告が出るようになっており、CbCの仕様を満たしているかどうかは、すぐにわかるようになっている。 +末尾最適化が行われない場合は, 警告が出るようになっており, CbCの仕様を満たしているかどうかは, すぐにわかるようになっている. \subsection{アセンブリコードの評価} 以下の図 \ref{fig:evalCbC},\ref{fig:evalAsm} はそれぞれコンパイル前の CbC の code segment とコンパイル後, それに対応するアセンブリコードを示している. @@ -428,7 +426,7 @@ コンパイル前のコードが持つ factorial0 への継続はコンパイル後, call ではなく jmp 命令により実装されており, このことから tail call elimination が正しく行われていることがわかる. これより, CbC コンパイラを LLVM/clang 上で実装できたことがわかる. \subsection{実行速度の評価} -今回測定に使用したプログラムは conv1 と呼ばれるもので, これは Micro-C での測定や, GCC 上に CbC コンパイラを実装した際の評価にも使用されたものである.\footnote{conv1 のソースコードは付録 A に掲載する.} conv1 の行う処理は CbC の継続と計算を交互に行うもので, 引数 1 の時には CbC の継続を使用, 引数 2, 3 の時には Micro-C のための最適化が手動で施されたコードを使用するようになっている. 測定結果は表 \ref{result} に示される. 尚, GCC は最適化無しでは末尾最適化を行わないので除外している. この例題は末尾最適化抜きでは stack overflow で動作しない。 +今回測定に使用したプログラムは conv1 と呼ばれるもので, これは Micro-C での測定や, GCC 上に CbC コンパイラを実装した際の評価にも使用されたものである.\footnote{conv1 のソースコードは付録 A に掲載する.} conv1 の行う処理は CbC の継続と計算を交互に行うもので, 引数 1 の時には CbC の継続を使用, 引数 2, 3 の時には Micro-C のための最適化が手動で施されたコードを使用するようになっている. 測定結果は表 \ref{result} に示される. 尚, GCC は最適化無しでは末尾最適化を行わないので除外している. この例題は末尾最適化抜きでは stack overflow で動作しない. \begin{table}[htpb] \centering \begin{tabular}{|l|r|r|r|} \hline