TPL的Parallel.For过多地创建和销毁线程。如何保持线程数不变?

时间:2012-05-04 22:52:43

标签: c# task-parallel-library

我编写了一些代码来使用Parallel.For和线程局部变量。它基本上是一个大数组的总和,但是数组的元素在它们被求和的同时在for循环中显式计算。

我遇到的问题是我的线程局部变量是非常非常重的对象。他们占用200 MB的内存并不罕见。我注意到我的程序的内存使用量将达到2 gb,然后GC会将其降低到200 mb并且上下移动,这表明正在分配许多临时值。因为我需要几个线程局部变量,所以我将它们包装在一个struct对象中。这允许我在构造函数中添加一个Console.WriteLine,我看到很多我的对象被创建,而我只想在我的机器上每个核心有一个构造。我怎样才能强制它创建精确的(numberOfCores)线程并且只保留那些直到最后?

我添加了

ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2;

只有轻微的帮助。我仍然得到太多的结构构造。看起来我可以用options.TaskScheduler做些什么,但我似乎无法理解它的强大程度。看起来我可以自己滚动,这几乎是可怕的。如果可能,我不想这样做。

以下是我程序中相关的代码部分。

ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2;

Parallel.For<ThreadLocalData>(0, m, options,
    // Thread local variable initialization
    () => new ThreadLocalData(new DenseMatrix(r * r, r * r, 0),
                              new DenseMatrix(r * r, r * r, 0),
                              new DenseMatrix(r, r, 0)),
    // Per-thread routine
    (row, loop, threadLocalData) =>
    {
        threadLocalData.kronProductRight.Clear();
        for (int column = 0; column < n; ++column)
        {
            if ((int)E[row, column] == 1)
                threadLocalData.kronProductRight.Add(Yblocks[column], threadLocalData.kronProductRight);
        }
        MathNetAdditions.KroneckerProduct(Xblocks[row], threadLocalData.kronProductRight, threadLocalData.kronProduct);
        threadLocalData.subtotal.Add(threadLocalData.kronProduct, threadLocalData.subtotal);
        return threadLocalData;
    },
    (threadLocalData) =>
    {
        lock (mutex)
        A.Add(threadLocalData.subtotal, A);
    }
);

2 个答案:

答案 0 :(得分:1)

查看这篇文章http://blogs.msdn.com/b/pfxteam/archive/2010/10/21/10079121.aspx特别是有关Parallel.For的部分,当初始化委托很昂贵时会出现性能问题。

从查看上面的代码很难说,但看起来你应该能够将ThreadLocalData的计算/数据部分与它的有状态/变异部分分开?理想情况下,您可以将对ThreadLocalData的不可变版本的引用传递给任何正在处理您的数字的内容。这样,无论如何,你只是处理一个实例。

答案 1 :(得分:0)

我没有深入了解你的问题(似乎你正在问phoog指出的错误问题),但要回答你的具体问题:

  

如何强制它创建精确(numberOfCores)线程并保持   只有那些直到最后?

你有一个完成这个的调度程序:

http://blog.abodit.com/2010/11/task-parallel-library-a-scheduler-with-priority-apartment-state-and-maximum-degree-of-parallelism/