0

いくつかの同期コードに同時実行性を追加したいのですが、そのプロセスでパフォーマンスの問題が見つかりました。これは理解が困難です。

以下のコードの実行結果は次のとおりです。

Mission Fibonacci1Async cost 9.4195388 seconds, value 75025
Mission Fibonacci2Async cost 0.2260129 seconds, value 75025

唯一の違いは、await Task.WhenAll(new Task[] { t1, t2 });という行が追加された 2 番目の関数です。、パフォーマンスを40倍にします。

誰でも私に説明できますか?

    static Task<int> Fibonacci1Async(int n)
    {
        return Task.Run<int>(() => Fibonacci1(n));
    }

    static int Fibonacci1(int n)
    {
        if (n == 0) return 0;
        else if (n == 1) return 1;
        else
        {
            var t1 = Fibonacci1Async(n - 1);
            var t2 = Fibonacci1Async(n - 2);
            return t1.Result + t2.Result;
        }
    }

    static Task<int> Fibonacci2Async(int n)
    {
        return Task.Run<int>(() => Fibonacci2(n));
    }

    static int Fibonacci2(int n)
    {
        if (n == 0) return 0;
        else if (n == 1) return 1;
        else
        {
            var t1 = Fibonacci2Async(n - 1);
            var t2 = Fibonacci2Async(n - 2);

            Task.WaitAll(new Task[] { t1, t2 });
            return t1.Result + t2.Result;
        }
    }

    static void Benchmark(Func<int, Task<int>> func)
    {
        DateTime time = DateTime.Now;
        var task = func(25);
        task.Wait();
        TimeSpan cost = DateTime.Now - time;
        Console.WriteLine("Mission {0} cost {1} seconds value {2}", func.Method.Name, cost.TotalSeconds, task.Result);
    }

    static void Main(string[] args)
    {
        Benchmark(Fibonacci1Async);
        Benchmark(Fibonacci2Async);
        Console.ReadKey();
        return;
    }
4

1 に答える 1

1

答えはTask.Waitinliningに関係していると思います。

t1.Result + t2.Resultでは、+演算子はその引数を (順番に) 左から右に評価します。t1そのため、 on をブロックしてからon をブロックしますt2

あなたのシステムでは、ほとんどの時間t1はすでに開始されていると思いますが、t2. この場合、新しいスレッド プール タスクを開始する代わりに、現在のスレッド プール タスクにTask.WaitAll「インライン化」できますが、 でブロックされます。t2+t1

これは単なる推測です。何が起こっているのかを正確に知るには、プロファイラーを使用する必要があります。

私のシステムではこれを再現できませんでした。プロセスにプロセッサ アフィニティが適用されていても、両方のバージョンがほぼ同じであることが常にわかります。

PS 命名規則Asyncはここでは実際には適用されません。このコードはasync/を使用していませんawait- タスク並列ライブラリを使用しています。

于 2012-04-22T12:20:18.967 に答える