2013-05-09 61 views
1

我写了两个简单的循环。Parrallel.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秒到第二个(!!!)。

这是为什么,我做错了什么?

+4

因为线程必须同步才能写入控制台?尝试做一些实际的工作。 – GSerg 2013-05-09 08:54:22

+0

起初,有一个数据库写入,而不是写入控制台,它仍然执行较慢。 – ohadinho 2013-05-09 08:57:13

+3

那么,db也是使锁/同步发生的共享资源。为了获得性能优势,您应该尽量避免在并行代码中使用这些资源。 – GSerg 2013-05-09 09:00:57

回答

0

我想你的代码中linqpad我用使用的Parallel.For

的for语句和12.5秒9秒,当您尝试访问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); 

这将下降的时候几个毫秒几百。

4

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

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

如果您想了解Parallel.For如何提高循环的性能,请考虑在循环内部进行一些计算,将结果保存为数组中的独占(每次迭代)索引,并确保这些计算不要以任何方式依赖于其他迭代的结果。

1

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

但是,只有当您具有最理想的并行编程代码时才会发生这种情况。很少有这样的算法。

代码的总体加速受限于无法并行化的代码部分。就像之前在评论和回答中所述,对于Console.WriteLine或Database acces,你的线程必须同步。所以这部分不能并行化。如果您的代码中有很大一部分不能并行执行,那么代码甚至可能比正常循环执行得慢。 (用于同步线程的时间)。

Amdhal的法则给了我们这个结论。

它说,它不能并行将限制整体加速从并行

阅读更多关于Amdhal定律这里的计划的一小部分:

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