3

这个问题最好征求高级用户的意见。

我正在优化一些数字运算代码,并有一些空闲的处理器内核。为了有效地利用它们,我正在研究一些使用任务Task.StartNew(这里根本不涉及 UI。

这里的一个关键元素是使用 ThreadPool,它可以为短期运行的任务带来性能优势,而不会产生线程创建的开销。然而,在某些情况下,更自然地考虑循环而不是任务(例如 Parallel.For)。

我了解任务使用 ThreadPool,但不确定 Parallel.For。问题是:

  • 哪些构造使用了 ThreadPool?
  • 可以将 Parallel.For 配置为使用 ThreadPool 还是总是会产生线程创建开销?
  • 不是主要问题的一部分,但任何与最大化并行性的链接都会有所帮助。

请注意,此问题特定于 .NET 4。目前无法选择升级到 4.5。

更新
根据 Daniel Kinsman 的评论,考虑以下几点:

System.Threading.Tasks.Parallel.For(0, 100, i => { System.Console.WriteLine("Is ThreadPool @ low priority: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread); });
System.Diagnostics.Process.GetCurrentProcess().PriorityBoostEnabled = true;
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.RealTime;
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
System.Threading.Tasks.Parallel.For(0, 100, i => { System.Console.WriteLine("Is ThreadPool @ high priority: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread); });

如果您有一台多核机器,IsThreadPoolThread 将根据您运行的应用程序数量返回不确定的结果。

4

1 回答 1

3

Parallel.For默认情况下,'always' 使用线程池来运行任务并且不会产生线程创建开销。

在当前版本的 .Net 4.0 CLR 中,Parallel.For内部使用ThreadPoolTaskScheduler类(一个内部类)来运行其任务。当然,这是内部细节可能会发生变化,但很可能Parallel.For会继续使用 ThreadPool 来运行其任务。如果您不想承担这种“风险”,那么您可以随时编写自己的TaskScheduler并将其提供给Parallel.For使用ParallelOptions 类

如果您有一台多核机器,IsThreadPoolThread 将根据您运行的应用程序数量返回不确定的结果。

解释:

ThreadPoolTask​​Scheduler 类是一个优化的任务调度程序,如果没有必要,它会尽量不在线程上运行任务,即如果任务可以立即执行,它会在可能不是线程的当前线程ThreadPool上执行。您看到的“假”输出适用于这种情况。但是如果它不能立即运行任务,它总是使用线程池将任务排队等待以后执行。

请注意,在这两种情况下,都没有线程创建“开销”(不完全正确,因为 ThreadPool 本身可能决定在某些启发式方法中在池中包含新线程)

您可以使用以下代码来确认这一点:

Thread.CurrentThread.Name = "MyThread";
System.Threading.Tasks.Parallel.For(0, 100, i => Console.WriteLine(i + ". Is ThreadPool: " + Thread.CurrentThread.IsThreadPoolThread + " Name: " + Thread.CurrentThread.Name));

您将能够注意到,对于所有“假”情况,线程名称都是“MyThread”。

关于最大化并行性,CPU 绑定的工作只能在可用 CPU 内核数量的范围内进行并行化。TPL 考虑到了这一点,非常适合和优化 CPU 绑定任务的并行计算。通过使用 TPL,您走在了正确的道路上,应该继续沿着这条道路前进 :)

于 2012-08-30T07:10:32.717 回答