Parallel.Foreach vs Foreach用于数据迁移过程

时间:2013-10-23 11:09:16

标签: c# asp.net performance parallel-processing parallel.foreach

我有一份车辆清单......对于每辆车,我正在做一些移民工作..

foreach (vehicles)
{

1 : Do database table migration for that vehicle
2 : Call an API and save them to database

}

为了提高性能,我将其平行化为:

Parallel.Foreach(vehicles)
{
--same
}
  1. 这是正确的做法吗?因为我的理解是,它将为每个请求的车辆创建新的线程,并且事情应该快速运行。

  2. 并行TASK会改善它吗?

  3. 保持最大并行数是否合适?如果是,如何确定该因素?

2 个答案:

答案 0 :(得分:5)

  1. 如果每个Vehicle项之间很少或没有依赖关系,这是正确的方法。换句话说,您(理想情况下)不应在lock的主体中对每个Action执行任何Vehicle(或其他同步原语)。但是,如果您的代码中有lock个,那么它们应该在代码的一部分上执行得比方法的其余部分快得多:

    Parallel.ForEach(vehicles, v => 
    {
        // Some code that takes long to execute
        lock(_syncRoot)
        {
            _totalProcessedVehicles ++;
        }  
    })
    

    Parallel.Foreach NOT 为每个Vehicle实例创建一个线程 - 它将生成多个线程,并为每个线程提供一大块要处理的集合。线程数取决于您的硬件和可用资源。

  2. 没有。 Parallel.Foreach在内部使用Task,这样做会增加您的代码开销负担。此外,使用与上面相同的逻辑在不同的线程上调度和执行任务:每个线程处理一大块Task s。

  3. 我不建议指定最大程度的并行性 - 让CLR为你做这件事;在绝大多数情况下,它会做得很好。但是,如果您执行想要限制并行度,则Parallel.Foreach会有一个重载,它接受ParallelOptions类型的参数。使用属性MaxDegreeOfParallelism来限制并行度。

答案 1 :(得分:2)

  1. 方法还可以,只需确保您的功能1和2是线程安全的(不要共享公共资源或至少同步它们的用法)

  2. 可能取决于瓶颈是什么,例如:如果你只有一个CPU,并且你的问题有CPU,因为瓶颈并行化不会给你带来任何东西。如果您有多个内核(CPU)而不是CPU限制问题,则并行化将非常有用。 在您的情况下,限制也可以是您迁移数据的数据库,充斥它甚至可能使数据更糟。

  3. 再次取决于你所遇到的瓶颈,如果是CPU的并行化程度高于你的CPU内核数量不会给你带来任何东西,那么相反它会减慢它的速度。线程会占用资源。根据经验,我主要选择CPU限制问题的核心数为-1,这样系统的其余部分仍然可以响应。

  4. 对于foreach循环中的小型甚至简单工作负载,初始化Parallel.Foreach的开销也可能会消耗掉这些好处。

    一般情况下,试一试并根据具体情况来决定。