我有一份车辆清单......对于每辆车,我正在做一些移民工作..
foreach (vehicles)
{
1 : Do database table migration for that vehicle
2 : Call an API and save them to database
}
为了提高性能,我将其平行化为:
Parallel.Foreach(vehicles)
{
--same
}
这是正确的做法吗?因为我的理解是,它将为每个请求的车辆创建新的线程,并且事情应该快速运行。
并行TASK会改善它吗?
保持最大并行数是否合适?如果是,如何确定该因素?
答案 0 :(得分:5)
如果每个Vehicle
项之间很少或没有依赖关系,这是正确的方法。换句话说,您(理想情况下)不应在lock
的主体中对每个Action
执行任何Vehicle
(或其他同步原语)。但是,如果您的代码中有lock
个,那么它们应该在代码的一部分上执行得比方法的其余部分快得多:
Parallel.ForEach(vehicles, v =>
{
// Some code that takes long to execute
lock(_syncRoot)
{
_totalProcessedVehicles ++;
}
})
Parallel.Foreach
将 NOT 为每个Vehicle
实例创建一个线程 - 它将生成多个线程,并为每个线程提供一大块要处理的集合。线程数取决于您的硬件和可用资源。
没有。 Parallel.Foreach
在内部使用Task
,这样做会增加您的代码开销负担。此外,使用与上面相同的逻辑在不同的线程上调度和执行任务:每个线程处理一大块Task
s。
我不建议指定最大程度的并行性 - 让CLR
为你做这件事;在绝大多数情况下,它会做得很好。但是,如果您执行想要限制并行度,则Parallel.Foreach
会有一个重载,它接受ParallelOptions
类型的参数。使用属性MaxDegreeOfParallelism
来限制并行度。
答案 1 :(得分:2)
方法还可以,只需确保您的功能1和2是线程安全的(不要共享公共资源或至少同步它们的用法)
可能取决于瓶颈是什么,例如:如果你只有一个CPU,并且你的问题有CPU,因为瓶颈并行化不会给你带来任何东西。如果您有多个内核(CPU)而不是CPU限制问题,则并行化将非常有用。 在您的情况下,限制也可以是您迁移数据的数据库,充斥它甚至可能使数据更糟。
再次取决于你所遇到的瓶颈,如果是CPU的并行化程度高于你的CPU内核数量不会给你带来任何东西,那么相反它会减慢它的速度。线程会占用资源。根据经验,我主要选择CPU限制问题的核心数为-1,这样系统的其余部分仍然可以响应。
对于foreach循环中的小型甚至简单工作负载,初始化Parallel.Foreach的开销也可能会消耗掉这些好处。
一般情况下,试一试并根据具体情况来决定。