为什么C#Parallel.Invoke很慢?

Luk*_*uka 3 c# multithreading task task-parallel-library

我这样做:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

因此,做一个100万次的循环并将项目添加到两个不同的词典.问题是需要11秒,这比普通顺序方法(没有任务/线程)多5倍,仅需2秒.不知道为什么.

Aus*_*nen 10

像其他人所说或暗示的那样,由于并行化的开销,并行代码并不总是更快.

话虽这么说,你的代码是并行地向2个字典添加一个项目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);
}
Run Code Online (Sandbox Code Playgroud)


And*_*rey 6

使用并行调用存在一定的开销,并且可以跨多个内核/ CPU分配工作.在这种情况下,开销大于有用工作分配的实际收益,因此这就是您看到显着差异的原因.尝试使用更繁重的操作,您将看到差异.


Wor*_*mbo 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);
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

这应该快得多,因为两个线程只被初始化一次然后运行完成.在您的版本中,您每次调用每个lambda表达式1000000次,每次等待两次完成后再继续.

Parallel.Invoke真的意味着用于更长时间的运行.否则,设置并行任务并等待它们全部完成的开销只会杀死并行运行任务所获得的任何性能.