Parallel.For循环执行速度比for慢

时间:2013-05-09 08:52:15

标签: c# multithreading

我写了两个简单的循环。

一个是使用标准'for':

Stopwatch sw = Stopwatch.StartNew(); 

            for (int i = 0; i < 1000000; i++)
            {
                Console.WriteLine(i);
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            Console.ReadKey();

其次是使用Parrallel.For,它假设更快:

sw.Restart();
            Parallel.For(0,1000000,i =>
                    {
                        Console.WriteLine(i);
                    });              

            sw.Stop();
            Console.WriteLine(sw.Elapsed);

不幸的是,第一次执行需要大约53秒,第二次执行需要大约1分50秒。(/ p)

为什么会这样,我做错了什么?

3 个答案:

答案 0 :(得分:4)

Parallel.For不应该更快地循环。它应该使其迭代执行并行

在您的尝试中,您使用的代码使用的资源无法与通过并行化循环提供的任何速度提升相匹配(可能是因为它们需要同步,可能是因为没有足够的带宽等)。因此,您只是让线程竞争无法跟上它们的资源。您的场景根本不需要并行性(至少不是您尝试的方式)。

如果你想了解Parallel.For如何提高循环的性能,可以考虑在循环中进行一些计算,将结果保存到数组中的独占(对于每个迭代)索引并且make确保这些计算不依赖于其他迭代的结果。

答案 1 :(得分:1)

通过并行编程,您可以同时完成更多工作。它会使您的代码并行执行。当您第一次看并行编程时,您希望您的速度增加线性。像4核一样快4倍。

但是,只有当您拥有最理想的并行编程代码时,才会出现这种情况。很少有算法有这个。

代码的总速度受到无法并行化的代码部分的限制。如前所述,在评论和答案中,对于Console.WriteLine或数据库访问,您的线程必须同步。所以这部分不能并行化。如果你的代码中很大一部分不能并行执行,那么代码甚至可以比普通循环执行得慢。 (用于同步线程的时间)。

阿姆哈尔定律给出了我们这个结论。

  

它指出无法并行化的程序的一小部分将限制并行化可用的整体加速

在这里阅读更多有关阿姆达尔定律的内容:

http://en.wikipedia.org/wiki/Parallel_computing

答案 2 :(得分:0)

我在linqpad中尝试了你的代码我使用for语句获得了9秒,使用Parallel.For获得了12.5秒。

当您尝试访问I / O资源(如数据库或控制台输出)时,必须使用锁定机制同步线程。无论如何,我不建议并行访问数据库以进行插入或选择语句。

但是请尝试使用此更改代码:

 Stopwatch sw = Stopwatch.StartNew(); 
 StringBuilder str = new StringBuilder();

 for (int i = 0; i < 1000000; i++)
 {
      str.AppendLine(i.ToString());
 }

 sw.Stop();
 Console.WriteLine(sw.Elapsed);

 str = new StringBuilder();
 sw.Restart();

 Parallel.For(0,1000000,i =>
                {
                    str.AppendLine(i.ToString());
                });              

 sw.Stop();
 Console.WriteLine(sw.Elapsed);

这会将时间减少到几百毫秒。