平行f(c)的这种奇怪行为怎么解释呢

本文关键字:解释 平行 | 更新日期: 2023-09-27 18:27:48

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

基本上,我的处理看起来像(带有伪代码的c#)

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])})

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

正如我所说,这种处理方案只在短时间内消耗了我处理器的100%,然后下降到大约80-85%。在我的情况下,我将N设置为Environment.ProcessorsCount(=8);

如果有人愿意帮忙,我可以共享整个代码/存储库。

我试着调查并创建了一个新的控制台项目,并在那里放置了几乎Hello World of Parallel.Ford(),我根本不知道发生了什么。这可能是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++; });
        }
    }
}

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

平行f(c)的这种奇怪行为怎么解释呢

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

至于问题的第一部分,我想问题在于传递给Parallel.For的索引范围。而不是[0,CPU核的数量),它应该等于数据的索引范围。