函数并行执行,实例数量合理

Parallel execution of function and reasonable number of instances

我有一个对象列表,我必须对每个对象做一些详细说明,所有这些都在尽可能短的时间内完成。

由于这些阐述相互独立,我们决定与 Parallel.ForEach 并行进行。

Parallel.ForEach(hugeObjectList,
    new ParallelOptions { MaxDegreeOfParallelism = 50 },
    obj => DoSomeWork(obj)
);

因为在 ParallelOptions.MaxDegreeOfParallelism 上设置一个巨大的数字(例如 50 或 100)对我来说似乎不合理,我们如何才能找到处理这个列表的最佳并行任务数?

Parallel.Foreach 是否在不同的内核上启动 DoSomeWork? (所以,既然我们有 4 个核心,正确的并行度应该是 4?)

我想这说明了一切

By default, For and ForEach will utilize however many threads the underlying scheduler provides, so changing MaxDegreeOfParallelism from the default only limits how many concurrent tasks will be used.

MSDN

询问平台应该会让您接近最佳状态(对于 CPU 绑定工作)。

new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount  },

什么都不做是另一个很好的选择,即

//new ParallelOptions { MaxDegreeOfParallelism = 50 },

编辑

there's a lot of io with a database ...

这使 MaxDegreeOfParallelism = 1 成为另一个非常好的候选人。或者可能是 2.

您真正应该研究的是 async/await 和异步数据库调用。不是并行 class.

唯一确定的方法就是测试它。更多的线程并不等于更好的性能,而且通常会产生更差的性能。一些想法:

  1. 为单线程设计算法,然后在其周围添加Parallel.For是没有意义的。您必须更改算法以利用多线程,否则并行处理的好处将很小或为负。

  2. 如果您正在从磁盘读取数据或通过网络连接下载数据,服务器能够以您获取数据的速度为您提供数据,您可能会发现 producer/consumer 模式表现最好。如果处理的计算量很大,请使用多个消费者线程(我倾向于使用 Num Cores - 2。一个用于 UI,一个用于生产者)。如果计算成本不高,使用多少消费者线程都无关紧要。

  3. 如果您从 Internet 从各种来源下载数据,并且服务器需要时间来响应,您应该启动相当多的线程(50-100 并不疯狂)。这是因为线程只会坐在那里等待服务器响应。