16

2の累乗を計算する2つの方法で実行時間を測定しました。

1)インライン

result = b * b;

2)簡単な関数呼び出しで

result = Power(b);

デバッグモードで実行している場合、すべてが期待どおりです。関数の呼び出しは、計算をインラインで実行するよりもかなりコストがかかります(ラインで385ミリ秒、関数呼び出しで570ミリ秒)。

リリースモードでは、コンパイラが非常に小さな関数を内部的にインライン化するため、コンパイラが関数呼び出しの実行時間を大幅に短縮することを期待しPower()ます。しかし、関数呼び出しが手動のインライン計算よりも高速であるとは思いません。

最も驚くべきことに、これが当てはまります。リリースビルドでは、最初の実行には109ミリ秒が必要であり、呼び出しを伴う2回目の実行にはPower()62ミリ秒しか必要ありません。

関数呼び出しは、手動のインライン化よりもどのように高速になりますか?

これがあなたの複製のためのプログラムです:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting Test");

        // 1. Calculating inline without function call
        Stopwatch sw = Stopwatch.StartNew();

        for (double d = 0; d < 100000000; d++)
        {
            double res = d * d;
        }

        sw.Stop();
        Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);

        // 2. Calulating power with function call
        Stopwatch sw2 = Stopwatch.StartNew();

        for (int d = 0; d < 100000000; d++)
        {
            double res = Power(d);
        }

        sw2.Stop();
        Console.WriteLine("Function: " + sw2.ElapsedMilliseconds);

        Console.ReadKey();
    }

    static double Power(double d)
    {
        return d * d;
    }
}
4

3 に答える 3

50

あなたのテストは間違っています。2番目の部分int dでは、doubleの代わりに使用します。多分それは時差を説明します。

于 2013-03-25T10:11:04.543 に答える
22

Xavierが正しく検出したため、一方のループでdoubleを使用し、もう一方のループでintを使用しています。両方を同じタイプに変更すると、結果は同じになります-私はそれをテストしました。

さらに、ここで実際に測定しているのは、加算と比較の期間です。の二乗の期間は、単に発生していないため、測定していませd。リリースビルドでは、結果が使用されないため、オプティマイザーはループの本体を完全に削除します。これは、ループの本体をコメントアウトすることで確認できます。期間は同じになります。

于 2013-03-25T10:17:09.807 に答える
3

Daniel Hilgarthは正しいです。結果が使用されていないため、計算はまったく行われていません(デバッグモードではおそらくそうではありません)。次の例を試してみてください。正しい結果が得られます。

static void Main(string[] args)
    {
        Console.WriteLine("Starting Test");
        var list = new List<int>();
        // 1. Calculating inline without function call
        Stopwatch sw = Stopwatch.StartNew();

        for (int d = 0; d < 100000000; d++)
        {
            int res = d * d;
            list.Add(res);
        }

        sw.Stop();
        Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);
        // 2. Calulating power with function call

        list = new List<int>();
        Stopwatch sw2 = Stopwatch.StartNew();

        for (int d = 0; d < 100000000; d++)
        {
            int res = Power(d);
            list.Add(res);
        }

        sw2.Stop();
        Console.WriteLine("Function: " + sw2.ElapsedMilliseconds);

        Console.ReadKey();
    }
于 2013-03-25T10:22:36.703 に答える