0

我有一个车辆清单..对于每辆车我都在做一些迁移工作..

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. 做并行任务会改善很多吗?

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

4

2 回答 2

5
  1. Vehicle如果您在每个项目之间几乎没有依赖关系,那么这是正确的方法。换句话说,您(理想情况下)不应该在每个执行lock的主体中包含任何(或其他同步原语)。但是,如果您的代码中确实有 s,则它们应该位于执行速度明显快于方法其余部分的部分代码上:ActionVehiclelock

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

    Parallel.Foreach不会为每个实例创建一个线程Vehicle- 它会产生几个线程,并会给每个线程一个集合的一部分来处理。线程数取决于您的硬件和可用资源。

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

  3. 我不建议指定最大程度的并行性——让CLR它们为你做吧;在绝大多数情况下,它会做得很好。但是,如果您确实想限制并行度,则存在Parallel.Foreach接受类型参数的重载ParallelOptions。使用该属性MaxDegreeOfParallelism来限制并行度。

于 2013-10-23T11:38:10.357 回答
2
  1. 方法没问题,只要确保你的函数 1 和 2 是线程安全的(不要共享公共资源或至少同步它们的使用)

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

  3. 同样,这取决于您遇到的瓶颈,如果是 CPU,则比您的 CPU 内核数更高的并行化程度不会给您带来任何好处,相反,它会减慢速度,因为线程的切换会消耗资源. 根据经验,我主要为 CPU 有限的问题选择核心数 -1,以便系统的其余部分仍然可以响应。

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

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

于 2013-10-23T11:28:39.860 回答