多くの業界で使用されているコンパイラで、継続渡しスタイルよりも静的単一割り当てが優先されるのはなぜですか?


15

静的単一割り当て(SSA)に関するウィキペディアのページによると、SSAはLLVM、GCC、MSV、Mono、Dalvik、SpiderMonkey、V8などの大規模で有名なプロジェクトで使用されていますが、継続渡しスタイルを使用するプロジェクトのページ(CPS)は比較して少し欠けています。

私は、CPSが主に機能言語を実装するコンパイラーとインタープリターによって好まれるというこの考えを持っています-特に、HaskellとSchemeは、突然変異の制限またはファーストクラスの継続サポートの必要性のために、CPSスタイルに強い傾向があるようです(私は推測します) Smalltalkでもこれが必要になる可能性があります)。私がCPSを使用している主要な文献は、主にSchemeに取り組んでいるか、何らかの点でSchemeに関連している文献のようです。

採用の勢いのほかに、SSAが業界で使用される特別な理由はありますか?SSAとCPSは密接な関係があります。つまり、別の観点から述べることは簡単ですが、情報表現はCPSにとってはコンパクトであるか、効率が低い可能性があります。


2
IIRCは、従来のデータフロー分析の時代に設計された命令型言語の従来の最適化は、CPSよりも簡単にSSAに転送されます。慣性は何かを数える
仮名

回答:


9

典型的な命令型言語の多くのコンパイラ実装者は、単にCPSおよびCPSベースのコンパイル手法に精通していないと思います。関数型プログラミングコミュニティでは、CPSとCPSベースのコンパイルの両方が非常によく知られている手法であり、後者はGuy Steeleの研究によるものです。それでも、FPコミュニティでも、言語自体がなどの制御演算子をサポートしていない限り、ほとんどのコンパイラーはCPSベースのコンパイル手法を使用しませんcall/cc。以上のような行政正規形(時々とも呼ばれる(ANF)単項正規形密接に明らかになるであろう理由のために関連している)を有する使用されているCPSが行うよりも、SSAにも、タイトな関係を

記憶が正しければ、管理標準形式は、CPSベースのコンパイルが、ソースコードの何にも対応していない中間コードのベータ版の再実行につながるという事実から名付けられました。これらは「管理上の再実行」と呼ばれていました。これらはコンパイル時に削減できますが、そもそも管理上の再実行なしでコードを出力するCPS変換の実行に関する多くの研究がありました。その後の目標は、すべての「管理」再実行が削減された標準形式で出力を生成することであり、これが管理標準形式の起源でした。これを2段階のプロセス(CPS変換、管理上のredexeの削減)として(nの最適化)表示することには、それほど多くの利点がないことに気付くのに時間がかかりませんでした。特に、管理標準形式は、Haskellで最も顕著に(手で)実行されるモナドスタイルのように見えます。CPS変換は、たまたまCPSモナドを使用しているモナドスタイルへの変換として理解できます(したがって、異なる評価順序に対応するモナドスタイルに「変換」する方法は本当に複数あります)。ただし、一般的には、まったく異なるモナドを使用している可能性があります。そのため、モナドスタイルへの変換、つまり管理標準形式への変換は、特にCPSとは特に関係ありません。

それでも、CPS対ANFにはいくつかの利点がありました。特に、ベータ削減など、ANFの(一見)アドホックルールを必要とする標準的な最適化だけでCPSで実行できる特定の最適化がありました。モナドの観点から見ると、これらのルールは通勤変換に対応しています。結論としては、どのルールを追加する必要があるのか​​、そしてその理由を説明できる理論があります。最近の論文では(論理的な観点からの)この(新しいと)かなり明確に説明しますとその関連作業区間は、私が言及トピックに関する文献に簡潔な、しかし、まともな調査および参照として機能します。

CPSの問題は、その主な利点の1つに関連しています。CPS変換を使用するとcall/cc、などの制御演算子を実装できますが、これは、CPS中間コード内のすべての非ローカル関数呼び出しを潜在的に実行する制御効果として扱う必要があることを意味します。言語に制御演算子が含まれている場合、これは本来あるべきことです(ただし、ほとんどの関数はおそらく制御を実行していません)。言語に制御演算子が含まれていない場合、継続の使用に関するグローバルな不変量があり、それはローカルでは明らかではありません。これは、一般的なCPSコードで実行するのが適切ではない最適化が存在することを意味します。このマニフェストの1つの方法はデータおよび制御フロー分析の精度の変更。(CPS変換はいくつかの点で役立ちますが、他の点では害がありますが、ほとんどの場合、CPSの側面自体ではなく複製が原因です。)1もちろん、ルールを追加し、分析を調整してこれを補いますただし、CPSベースのコンパイルの主な利点の1つを部分的に無効にしました。つまり、多くの(一見)特殊目的のアドホック最適化が、汎用最適化(特にベータ削減)の特殊なケースになります。 )。

最終的に、言語に制御演算子がない限り、通常、CPSベースのコンパイルスキームを使用する理由はあまりありません。上記の問題を補うと、通常はCPSベースのコンパイルの利点がなくなり、CPSを使用しない場合と同等の結果が得られます。その時点では、CPSは複雑な外観の中間コードを作成しているだけで、あまりメリットはありません。2007年からのCPSベースのコンパイルの議論は、これらの問題のいくつかに対処し、CPS変換の異なる形式を使用するいくつかの他の利点を提示します。紙がもたらすものは、前に述べた(2017)紙によって部分的にカバーされています。

1 SSAとCPSの同等性により、これはほぼ不可能になりませんか?米国特許第一のものの一つ、この等価導入紙状態が等価でないことではないため作業任意 CPSコードを、それが言語の(それらが定義する)変換CPSの出力のための作業を行うことなく、制御オペレータ。


2
最初の回答からしばらく経ちましたが、10%以上を理解しているので、最終的に回答を受け入れることができます
...-CinchBlue

2

私はコンパイラの専門家ではないので、私が言ったことを一言で言ってください。本当のコンパイラの専門家が声をかけてくれることを願っています。

  • CPSされたコードは、非局所的に多くジャンプする傾向があり、キャッシュの局所性を損なうため、パフォーマンスが低下します。
  • CPSは、通常、スタックに多くのものを格納できる従来のコンパイルよりも高価なガベージコレクションを必要とします(割り当てと割り当て解除の方が高速です)。

どちらも、CPS変換によってコンパイルされたコードを比較的遅くすることを共謀しています。


2
CPSを変換したソースコード(またはソースからソースへの変換)と、中間言語であるCPSを使用していると思います。入力言語がのような制御効果をサポートしていないと仮定すると、call/ccたとえば、継続はスタックの分野で使用されます-ガベージコレクターは不要であり、継続は制御フローのエッジにほぼ対応しますグラフが表示されるので、余分なジャンプはありません。高階関数の汎用実装を使用して継続を実装する必要はありません。
デレクエルキンズは、

@DerekElkins OPが何を求めていたのかははっきりしませんでした。
マーティンバーガー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.