在嵌套循环中,应该在外部还是内部循环上使用Parallel.For?

时间:2012-07-29 18:51:55

标签: c# .net loops task-parallel-library

我正在将一些代码从.NET 2转移到4并在其他方面利用TPL。

虽然我确定这个问题肯定是在SO上的某个地方被问到的,但我找不到它。

我知道过度嵌套的TPL任务可能会对性能产生不利影响。

for (int y=0; y < h; y++)
    for (int x=0; x < w; x++)
        grid [x, y] = ((x + 1) * (y + 1));

您会将上面的外部或内部循环替换为TPL吗?为什么?如果有更多的嵌套水平怎么办?

这是替换内部循环的代码,在我的情况下表现更好1秒。

int w = 10000;
int h = 10000;
int [,] grid = new int [w, h];
int [] index = new int [w * h];
DateTime time = DateTime.Now;
ParallelOptions options = new ParallelOptions();

options.MaxDegreeOfParallelism = Environment.ProcessorCount;

time = DateTime.Now;
for (int y=0; y < h; y++)
{
    Parallel.For
    (
        0,
        w,
        options,
        x =>
        {
            grid [x, y] = ((x + 1) * (y + 1));
        }
    );
}
span = DateTime.Now.Subtract(time);
Console.WriteLine("Filled in " + span.TotalSeconds.ToString() + " seconds.");

time = DateTime.Now;
for (int y=0; y < h; y++)
{
    Parallel.For
    (
        0,
        w,
        options,
        (x, state) =>
        {
            if (grid [x, y] < index.Length)
            {
                index [grid [x, y]]++;
            }
            else
            {
                state.Break();
            }
        }
    );
}
span = DateTime.Now.Subtract(time);
Console.WriteLine("Indexed in " + span.TotalSeconds.ToString() + " seconds.");

3 个答案:

答案 0 :(得分:4)

在内部循环并行化时,您会看到更好的性能,因为rect[x,]与内存中的rect[x+1,]相邻而rect[,y]rect[,y+1]不相邻,因此并行化外部循环会导致更多争用相同的内存空间并减慢速度。

除了对外环进行parrelleizing应该更快,所以如果你切换内部和外部循环,然后在外部循环上做Parallel.For,你应该获得比当前任何一个测试更好的性能。

另外需要注意的是边界检查有点贵,所以你也可以通过使用不安全的代码/指针而不是循环遍历大型数组来看到一些性能提升。

答案 1 :(得分:0)

外部循环,因为使用内部循环会导致比外部循环更多的跨线程通信。

答案 2 :(得分:-1)

既不! 你有性能问题吗?如果您提供的代码示例是真实的,看起来您可以从jagged array中受益,其性能要好得多。