1

次のように定義された関数を考えてみましょう。

f(n, x) = F(n, x, f(n-1, x))
f(0, x) = g(x)

私のプログラムでは、 の値はnコンパイル時に常にわかっています。プログラムを最適化し、この関数でのループや再帰呼び出しを回避したいと考えています。コンパイラが式を最適化できるように、式全体f(n, x)をコンパイル時に生成する必要があります。

mixin直接的な解決策は、この式と useステートメントを含む文字列を「手動で」生成することです。私はこの方法が好きではありません。

コンパイラは、既知の深さで再帰を展開できる/想定されていますか?

つまり、次の関数は私が望む方法で最適化されます:

double f(uint n)(double x)
{
    static if(n == 0)
        return g(x);
    else
        return F(n, x, f!(n-1)(x));
}
4

1 に答える 1

3

私の知る限り、言語仕様の最適化は保証されていません。あなたの例はコンパイラーのために最適化するのにかなり些細なように見えますが。

簡単な実験:簡単な計算を行うスタブ関数g()とF()を作成しました。dmd -gc -O -inline"でコンパイル。objdumpでチェック:

0000000000426860 <_Dmain>:
  426860:   55                      push   %rbp
  426861:   48 8b ec                mov    %rsp,%rbp
  426864:   f2 48 0f 10 05 2b a7    rex.W movsd 0x2a72b(%rip),%xmm0        # 450f98 <_IO_stdin_used+0x38>
  42686b:   02 00 
  42686d:   be 0a 00 00 00          mov    $0xa,%esi
  426872:   48 bf 28 10 66 00 00    movabs $0x661028,%rdi
  426879:   00 00 00 
  42687c:   e8 6f 01 00 00          callq  4269f0 <_D3std5stdio4File14__T5writeTdTaZ5writeMFdaZv>
  426881:   31 c0                   xor    %eax,%eax
  426883:   5d                      pop    %rbp
  426884:   c3                      retq

ご覧のとおり、すべてが実際にコンパイル中に計算され、writelnの引数としてすぐに出力される単一の数値に置き換えられました。また、実行時にxが読み取られ、f()の呼び出しも行われない変更を確認しました。ASMのリストはかなり長いので、コピーしません。

また、コンパイル時にパラメーターがわかっている場合は、おそらくCTFE(コンパイル時関数評価)が保証されているため、より優れたソリューションです。

于 2012-09-13T17:22:01.527 に答える