3

私はこれをやっています:

    private static void Main(string[] args)
    {
        var dict1 = new Dictionary<int, string>();
        var dict2 = new Dictionary<int, string>();
        DateTime t1 = DateTime.Now;
        for (int i = 1; i < 1000000; i++)
        {
            Parallel.Invoke(
                  () => dict1.Add(i, "Test" + i), 
                  () => dict2.Add(i, "Test" + i) );
        }
        TimeSpan t2 = DateTime.Now.Subtract(t1);

        Console.WriteLine(t2.TotalMilliseconds);

        Console.ReadLine();
    }

したがって、for ループを 100 万回実行し、2 つの異なる辞書に項目を追加します。問題は、2 秒しかかからない通常のシーケンシャル メソッド (タスク/スレッドなし) の 5 倍以上である 11 秒かかることです。理由がわからない。

4

5 に答える 5

10

他の人が言ったり暗示したりしたように、並列化のオーバーヘッドにより、並列コードが常に高速であるとは限りません。

そうは言っても、コードは2 つの辞書に 1M の項目を並行して 1M 回追加していますが、2 つの辞書に 1M の項目を並行して追加する必要があります。違いは微妙ですが、最終的な結果は、シーケンシャル ケースよりも ~10% 高速なコードです (私のマシンでは)。

Parallel.Invoke(() => FillDictionary(dict1, 1000000), () => FillDictionary(dict2, 1000000));

...

private static void FillDictionary(Dictionary<int, string> toFill, int itemCount)
{
    for(int i = 0 ; i < itemCount; i++)
        toFill.Add(i, "test" + i);
}
于 2012-05-29T15:56:35.793 に答える
6

並列呼び出しを使用すると一定のオーバーヘッドが発生し、複数のコア/CPUに作業を分散できるという利点があります。この場合、オーバーヘッドは有用な作業の分散による実際のメリットよりも大きいため、大きな違いが見られます。より重い操作を使用してみてください。違いがわかります。

于 2012-05-29T15:43:13.247 に答える
5

それを次のように書き換えます。

Parallel.Invoke(
    () =>
    {
        for (int i = 0; i < 1000000; i++)
        {
            dict1.Add(i, "Test" + i);
        }
    },
    () =>
    {
        for (int i = 0; i < 1000000; i++)
        {
            dict2.Add(i, "Test" + i);
        }
    }
);

2 つのスレッドが正確に 1 回初期化されてから完了するまで実行されるため、これははるかに高速になるはずです。あなたのバージョンでは、各ラムダ式を1000000回呼び出しており、毎回両方が終了するのを待ってから続行しています。

Parallel.Invoke実際には、長時間実行される操作に使用することを意図しています。そうしないと、並列タスクをセットアップしてすべてのタスクが完了するのを待つというオーバーヘッドにより、タスクを並列に実行することで得られるパフォーマンスが損なわれるだけです。

于 2012-05-29T15:59:19.260 に答える
1

Parallel.Invoke「これらすべてのタスクを実行し、完了するまで待つ」ことを意味します。この場合、並行して実行するタスクは 2 つだけです。したがって、並列呼び出しのオーバーヘッドは、同時実行による潜在的な利益よりも大きくなります。

于 2012-05-29T15:44:56.860 に答える
0

2 つの異なる辞書に 100000 項目を追加する場合は、メソッドではなく、タスク間の作業負荷を分割する必要があります。このメソッドはコードと同じことを行いますが、私のマシンでは実装よりもはるかに高速です。

var dict1 = new ConcurrentDictionary<int, string>();
    var dict2 = new ConcurrentDictionary<int, string>();

    Parallel.Invoke(() =>
    {
        for(int i = 0; i < 500000; i++)
        {
            dict1[i] = "Test" +i;
            dict2[i] ="Test" +i;
        }
    },
    () =>
    {
        for(int i = 500000; i < 1000000; i++)
        {
            dict1[i] ="Test" +i;
            dict2[i] = "Test" +i;
        }
    });
于 2012-05-29T16:01:14.373 に答える