for循环和Parallel.For()之间的性能损失,MaxDegreeOfParallelism为1

时间:2014-10-02 20:42:14

标签: c# performance task-parallel-library

我想做以下事情:

int firstLoopMaxThreads = 1; // or -1
int secondLoopMaxThreads = firstLoopMaxThreads == 1 ? -1 : 1;

Parallel.For(0, m, new ParallelOptions() { MaxDegreeOfParallelism = firstLoopMaxThreads }, i =>
{
    //do some processor and/or memory-intensive stuff
    Parallel.For(0, n, new ParallelOptions() { MaxDegreeOfParallelism = secondLoopMaxThreads }, j =>
    {
        //do some other processor and/or memory-intensive stuff
    });
});

当secondLoopMaxThreads = 1时,将内部Parallel.For循环与正常for循环交换是否值得,性能明智?常规for循环和具有MaxDegreeofParallelism = 1的Parallel.For循环之间的性能差异是什么?

2 个答案:

答案 0 :(得分:1)

循环 body 在两个版本中的表现同样出色,但即使对于单线程执行,循环本身也会慢得Parallel.For。每个元素都需要调用一个委托。这比递增循环计数器要慢得多。

如果你的循环体有意义的话,那么循环开销会因有用的工作而相形见绌。只要确保您的工作项目不是太小,您就不会注意到差异。

嵌套并行循环很少是个好主意。如果工作项既不太小也不太大,单个并行循环通常是最好的。

答案 1 :(得分:1)

这取决于你所谈论的迭代次数以及你所谈论的性能水平是否值得。在你的上下文中,1ms被认为是很多,还是一点点?

我做了如下的基本测试(因为Thread.Sleep并不完全准确..虽然for循环每次测量15,000毫秒到1毫秒内)。超过15,000次迭代重复5次,与循环标准相比,通常会增加约4ms的开销......但当然结果会因环境而异。

for (int z = 0; z < 5; z++)
{
    int iterations = 15000;

    Stopwatch s = Stopwatch.StartNew();

    for (int i = 0; i < iterations; i++)        
        Thread.Sleep(1);        

    s.Stop();

    Console.WriteLine("#{0}:Elapsed (for): {1:#,0}ms", z, ((double)s.ElapsedTicks / (double)Stopwatch.Frequency) * 1000);

    var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
    s = Stopwatch.StartNew();

    Parallel.For(0, iterations, options, (i) => Thread.Sleep(1));

    s.Stop();

    Console.WriteLine("#{0}: Elapsed (parallel): {1:#,0}ms", z, ((double)s.ElapsedTicks / (double)Stopwatch.Frequency) * 1000);
}