如何解释parallel.for(c#)的这种奇怪行为

时间:2014-10-26 12:41:41

标签: c# multithreading task-parallel-library tap parallel.for

我的神经网络库存在问题。它使用多线程来加速计算。但是在运行约30-60秒后,我的程序不再使用100%的i7 3610QM 4cores 8threads了。

基本上我的处理看起来像(c#with pseudocode)

for each training example t in training set
    for each layer l in neural network
        Parallel.For(0, N, (int i)=>{l.processForward(l.regions[i])})
    for each layer l in neural network (but with reversed order)
        Parallel.For(0, N, (int i)=>{l.backPropageteError(l.regions[i])})

其中region是图层要处理的神经元预先计算区域的列表。每个区域的大小与当前图层的1 / N相同,因此任务大小相同,以最大限度地减少其他线程需要等待最长任务完成的机会。

就像我说的那样,这种处理方案仅在短时间内消耗100%的处理器然后降低到大约80-85%。在我的例子中,我将N设置为Environment.ProcessorsCount(= 8);

如果有人愿意提供帮助,我可以分享整个代码/存储库。

我试图调查并创建了新的控制台项目,并将几乎Hello World的Parallel.For()放在那里,我根本无法分辨出发生了什么。这可能是Parallel.For()的另一个问题,但我也希望你解决这个问题。这是代码:

class Program
{
    static void Main(string[] args)
    {
        const int n = 1;

        while (true)
        {
            //int counter = 0; for (int ii = 0; ii < 1000; ++ii) counter++;

            Parallel.For(0, n, (int i) => { int counter = 0; for (int ii = 0; ii < 1000; ++ii) counter++; });
        }

    }
}

在这段代码中,我经常(while循环)创建一个有一些工作要做的任务(n = 1)(增加计数器一千次)。据我所知,Parallel.For块执行/等待所有并行调用完成。如果这是真的,它应该与评论部分做同样的工作(提供n = 1)。但是在我的电脑上,这个程序使用100%的CPU,就像有多个线程的工作一样!怎么可能?当我切换到注释版本时,程序使用不到20%的CPU,这是我的预期。请帮我理解这个行为。

1 个答案:

答案 0 :(得分:0)

正如@TaW所说,他们是并行的代价。这就是f()Parallel.For(0, n, _ => f())不等同的原因。并行版本引起线程调度和上下文切换。在您的情况下,f()的执行时间与线程调度开销相当。这就是为什么使用并行版本会降低性能的原因。 Parallel.For等待操作完成,但是完成得非常快,以至于几个线程在很短的时间内在CPU上运行(请记住,每次调用Parallel.For时,它都可以选择不同的线程来运行{ {1}}在不同的CPU内核上。

至于问题的第一部分,我猜问题在于传递给f()的索引范围。而不是[0,CPU核心数量],它应该等于数据的索引范围。