18

我运行一个多线程循环的执行过程中更改parallelOptions.MaxDegreeOfParallelism:是否有可能一个Parallel.ForEach

protected ParallelOptions parallelOptions = new ParallelOptions(); 

parallelOptions.MaxDegreeOfParallelism = 2; 
Parallel.ForEach(items, parallelOptions, item => 
{ 
// Loop code here 
}); 

我想并行循环的执行期间改变parallelOptions.MaxDegreeOfParallelism减少或增加一些线程。

parallelOptions.MaxDegreeOfParallelism = 5; 

它似乎并没有增加线程。有没有人有任何想法?

+0

你能解释一下你为什么想这样做吗?如果需要的话,它已经增加了自己的线程数,直到达到指定的最大值,或者如果合适的话,它将使用更少的线程数。 – 2010-09-13 23:02:06

+1

主要用于在共享服务器上使用太多资源时启动应用程序。我得到的服务器运行在100%,这降低了服务器上其他应用程序的响应度。 – 2010-09-13 23:04:59

+0

这是一个CPU绑定问题或其他“资源”,如磁盘? – 2010-09-13 23:39:40

回答

3

我不希望在调用ForEach之后可以改变并行度。据我所知,ForEach将确定它可以创建多少个线程,创建多个分区,并创建线程以在这些分区上运行。没有必要说,“哦,等等,他改变了我们的资源分配,让我重新分割数组并重新分配线程。”

+0

是的,我确定我同意你的理解,但你能请添加参考链接? – 2013-04-16 13:17:07

6

甚至试图做到这一点的问题是,这是一个难题。对于初学者,您甚至可以如何可靠地观察CPU和磁盘利用率?很少采样CPU会对实际发生的情况产生不良影响,并且采样磁盘利用率更难。其次,什么是你的任务的粒度,以及你能够迅速改变正在运行的数字。第三,随着时间的推移,事情会迅速发生变化,因此您需要对观察结果应用某种过滤。第四,线程的理想数量将取决于代码实际运行的CPU。第五,如果你分配太多的线程,你会在它们之间颠簸而不是做有用的工作。

请参阅http://msdn.microsoft.com/en-us/magazine/ff960958.aspx以了解.NET中的线程池如何处理决定使用多少个线程的复杂任务。

您也可以使用反射器并查看TPL用于分配线程的代码并避免不必要的上下文切换 - 这很复杂,甚至不考虑磁盘访问!

您可以改为尝试在低优先级的线程上执行任务(创建自己的TaskScheduler,其优先级低于正常运行线程实际上非常简单)。至少可以确保您可以运行100%的CPU而不会影响系统的其他部分。与线程优先级混淆本身充满了问题,但如果这是一个纯粹的后台任务,它可以是直接的,并可能有所帮助。

通常情况下,磁盘利用率是真正的罪魁祸首,当涉及到其他应用程序在一个贪婪的应用程序的痛苦。 Windows可以轻松地在应用程序之间分配CPU,但是当涉及相对较慢的磁盘访问时,这是另一回事。与其试图动态调整您正在运行的线程数量,您可能需要简单地调整应用程序的大小,使其不会太频繁地访问磁盘。在不改变有多少线程处于活动状态的情况下,您可以这样做。

您也可以查看SetPriorityClass作为通知操作系统的一种方式,即您的进程不像系统上运行的其他应用程序那么重要,有关更多信息,请参见How can I/O priority of a process be increased?。但是,这假定你的整个过程不那么重要,而不仅仅是这一部分。

相关问题