PyPyの論文つぶやき

動的言語、JITの研究している知人がPyPyの論文読みながらつぶやいてたので、まとめとく。
15
前へ 1 2 ・・ 6 次へ
Ryotaro Ikeda @chlere

guardによる定数置き換え(プロモーション)はプリミティブ型でしか使えず、変数が実際にはObjectに関連付けられる事が多いインタプリタ言語ではあまりクリティカルではない。 #pypy

2011-08-23 14:37:20
Ryotaro Ikeda @chlere

例えばObjectの持つプロパティのうち、コンストラクタでのみ値が変更される部分はConstと見なせない事はないが、C++等にあるアクセスレベルのフィールドという考え方がRPythonにはないので実行中にConstを完璧に保障する方法はない。ので別のヒントにより扱う。 #pypy

2011-08-23 14:40:15
Ryotaro Ikeda @chlere

(てかPyPyって「She」なのね。何か作為的なものを感じますね。) #pypy

2011-08-23 14:43:51
Ryotaro Ikeda @chlere

PyPyのJITは  RTyping->apply_jit->WarmRunnerDesc->maybe_compile_and_run->compile_and_run_once->(guard placing)->(optimizations) の流れらしい #pypyja

2011-10-07 16:06:15
Ryotaro Ikeda @chlere

まずRTypingによって変数の型が決定され、低水準の命令列を含んだグラフを生成。(低水準とはPythonのa+bなどではなくIntAdd(...)のような形) #pypyja

2011-10-07 16:07:57
Ryotaro Ikeda @chlere

次にmetainterp/warmspot.pyで定義されているapply_jit関数を実行。これはJITコンパイラ生成の足がかりとなる関数で、この関数でバックエンドを決定し、WarmRunnerDescクラスのインスタンスを生成する。 #pypyja

2011-10-07 16:09:58
Ryotaro Ikeda @chlere

WarmRunnerDescは2つのJITのヒント(can_enter_jitとjit_merge_point)をグラフから探す。部分グラフになっているFunctionグラフのうちjit_merge_pointを含むものを特にポータルグラフと呼ぶ。 #pypyja

2011-10-07 16:11:56
Ryotaro Ikeda @chlere

このポータルグラフを、JITがJITの動作から抜けられるようにする為の特別な例外処理を加えるためにWarmRunnerDescが書き換える。(JITの範囲を指定したり、インタプリタ制御との境界を定義する為?) #pypyja

2011-10-07 16:13:50
Ryotaro Ikeda @chlere

そしてcan_enter_jitのヒントはwarmstate.pyで定義されているmaybe_compile_and_run関数に置き換えられる。これは、その対象となっている部分グラフがホットであるかどうかを調べ、コンパイルすべきかどうかを判定するものである。 #pypyja

2011-10-07 16:16:13
Ryotaro Ikeda @chlere

次にポータルグラフがcodewriterディレクトリ下のスクリプト群によってJITコンパイル可能なバイトコードに書き換えられる。このバイトコードが最終的にできるバイナリにそのまま組み込まれる。 #pypyja

2011-10-07 16:18:39
Ryotaro Ikeda @chlere

(これはつまり、コード全体がJITコンパイルできる訳ではなく、ヒントによって指定されたJITコンパイルに適した(JITコンパイルするかも知れない)部分だけをJITコンパイルできるバイトコードに変換し、その部分にJITコンパイルを限定するもののようだ) #pypyja

2011-10-07 16:20:40
Ryotaro Ikeda @chlere

以上でJITの生産はおしまい。このプロセスを辿ってJITが付与され生産されたインタプリタはトレーシングJITという機能(Tamarin Tracingで初登場したアレ)をもつ。 #pypyja

2011-10-07 16:22:05
Ryotaro Ikeda @chlere

まずインタプリタは通常通りの実行動作をし、メインループの終わり(can_enter_jitヒントがある場所)に来たらWarmEnterStateクラスのmaybe_compile_and_runメソッドを呼び出す。 #pypyja

2011-10-07 16:27:39
Ryotaro Ikeda @chlere

( つまるところ、PyPyの開発者にとってはgreenな変数=大抵そのインタプリタのプログラムカウンタだろ という認識の模様。それを用いてプログラムのどこの部分が何回実行されたかを見てる ) #pypyja

2011-10-07 16:31:34
Ryotaro Ikeda @chlere

おそらくPyPyの研究の新規性としてもっとも評価されている一番のウリはこの「Meta Tracing」である筈なので、そういう意味ではgreenな変数,redな変数はPyPy特有のタームだと言えるかな。 #pypyja

2011-10-07 16:36:19
Ryotaro Ikeda @chlere

実際にこのトレースを行うのはMetaInterpとMIFrameクラスで、これらはプラットフォーム非依存のオブジェクトであり、metainterp/pyjitpl.pyで定義されている #pypyja

2011-10-07 16:39:38
Ryotaro Ikeda @chlere

maybe_compile_and_run()関数によってこれらのMetaInterpクラスが生産され、またそれの持つcompile_and_run_once()メソッドが呼ばれる。 #pypyja

2011-10-07 16:42:32
Ryotaro Ikeda @chlere

このメソッドによってMIFrameが、jit_merge_pointヒントによって渡されたgreenな変数とredな変数を用いて初期化される。このMIFrameを使ってホットになったポータルグラフをJITコンパイルできる。 #pypyja

2011-10-07 16:44:30
Ryotaro Ikeda @chlere

ループの引数(ループ自体を一つの関数グラフとして見る)はBoxesという概念によってラップされて渡される。これらの概念には、大きく分けてConstant boxesとNormal boxesの二つがある。 #pypyja

2011-10-07 16:47:41
Ryotaro Ikeda @chlere

それぞれのBoxは、変数の値と型情報を含んだものである(JITコンパイルには型情報が必要なため)。Constant boxはトレーシング中に値が分かる変数が格納され(これにはpromoteによって定数になった変数も含まれる)、必ずしもコンパイル時定数でなくてよい。 #pypyja

2011-10-07 16:50:37
Ryotaro Ikeda @chlere

Normal boxesにはConstant boxesに入らないものが格納される。それぞれのBoxはオブジェクトとして表現されている。(BoxInt,BoxFloat,..,ConstInt,ConstFloat,..) #pypyja

2011-10-07 16:52:33
Ryotaro Ikeda @chlere

トレーシングはメタインタプリタが行い、これはJIT可能なバイトコードを実行順に命令列のリストとして集めるものである。このリストの単位を「トレース」という。 #pypyja

2011-10-07 16:55:47
Ryotaro Ikeda @chlere

それぞれの命令に引数が必要な場合は前述のBoxにパックされた状態でトレースされる。このトレーシング中に出現する命令列の定義は metainterp/resoperation.pyで定義されている。 #pypyja

2011-10-07 16:57:39
Ryotaro Ikeda @chlere

あとはGuard張ってトレースされた部分に最適化かけてコード生産しておしまい。この最適化の部分はpromoteとかtrace-elidableなどの新しい概念が出てくるので詳しくは最新のbolzの論文をご参照あれ。 #pypyja

2011-10-07 16:59:45
Ryotaro Ikeda @chlere

もしかして : 「pypy-jaからpyjitpl5.rstを引っ張ってきてそこにpushすればよかった 」 もしかしなくても:「しまった」 #pypyja

2011-10-07 17:00:29
前へ 1 2 ・・ 6 次へ