4

有没有办法限制 ThreadPool 对象将使用的处理器数量?根据文档,“您不能将工作线程的数量或 I/O 完成线程的数量设置为小于计算机中处理器数量的数字。”

那么如何限制我的程序不消耗所有处理器呢?

4

4 回答 4

12

经过一些实验,我想我有这个东西。我注意到ThreadPool将系统中的处理器数量视为当前进程可用的处理器数量。这对您有利。

我的 CPU 中有 4 个内核。尝试SetMaxThreads与 2 通话:

ThreadPool.SetMaxThreads(2, 2);

失败,因为我有 4 个核心,所以数字保持在初始值(我的系统为 1023 和 1000)。

但是,就像我最初所说的那样,ThreadPool仅考虑进程可用的处理器数量,我可以使用Process.ProcessorAffinity. 这样做:

Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(3);  

将可用处理器限制为前两个内核(因为 3 = 11 二进制)。再次调用SetMaxThreads

ThreadPool.SetMaxThreads(2, 2);

应该像魅力一样工作(至少它对我有用)。只需确保在程序启动时使用关联设置!

当然,我不会鼓励这种hack,因为无论如何你的进程在其执行的整个过程中都会被有限数量的核心卡住。

于 2012-07-11T13:03:31.943 回答
4

线程池专门设计用于消除手动管理线程的所有麻烦。OS 任务调度器已经研究了很多年,并且在调度任务执行方面做得非常好。调度程序考虑了多个选项,例如线程优先级、内存位置和与处理器的接近程度等。除非您对这些进程有深入的了解,否则最好不要设置线程亲和性。

如果我可以引用文档

线程亲和性强制线程在特定的处理器子集上运行。通常应避免设置线程亲和性,因为它会干扰调度程序跨处理器有效调度线程的能力。这会降低并行处理产生的性能增益。线程亲和性的适当使用是测试每个处理器。

可以设置Thread亲和性(相关帖子),您需要为此创建自己的线程对象(而不是来自线程池的对象)。据我所知,您不能为池中的线程设置线程亲和性。

于 2012-07-11T12:19:07.120 回答
1

由于 SetMaxThreads 不允许您设置否。线程数低于 no。处理器的最佳选择是在 TPL 中编写自己的 TaskScheduler,通过对任务进行排队来限制并发性。然后,您可以使用该调度程序创建任务,而不是将项目添加到线程池。

请参阅 如何:创建限制并发程度的任务计划程序

于 2012-07-11T12:00:26.803 回答
1

您通常不会限制线程池,而是限制程序一次生成的线程数。Task Parallel Library允许您设置MaxDegreeOfParallelism 或者您可以使用Semaphore

于 2012-07-11T12:02:01.480 回答