Win32线程调度

Posted

技术标签:

【中文标题】Win32线程调度【英文标题】:Win32 Thread scheduling 【发布时间】:2009-03-18 04:25:11 【问题描述】:

据我了解,Windows 线程调度程序不会区分属于两个不同进程的线程,前提是它们都具有相同的基本优先级。我的问题是,如果我有两个应用程序,一个只有一个线程,另一个有 50 个线程,所有线程都具有相同的基本优先级,这是否意味着第二个进程比第一个进程享有更多的 CPU 时间?

【问题讨论】:

如果一个应用程序有 50 个进程而另一个应用程序只有一个会怎样。第一个应用程序是否应该获得更多的 CPU 时间? 【参考方案1】:

Windows 中的调度处于线程粒度。这种方法背后的基本思想是进程不运行,而只提供资源和线程运行的上下文。回到您的问题,因为调度决策是严格基于线程做出的,所以没有考虑线程属于哪个进程。在您的示例中,如果进程 A 有 1 个可运行线程,进程 B 有 50 个可运行线程,并且所有 51 个线程都具有相同的优先级,则每个线程将获得 1/51 的 CPU 时间-Windows 不会给出 50处理 A 的 CPU 百分比和处理 B 的 50%。 要了解线程调度算法,您必须首先了解 Windows 使用的优先级。您可以在这里refer 快速参考。

尝试阅读Windows Internals 以深入了解。

【讨论】:

信息也在这里:msdn.microsoft.com/en-us/library/… 因此可以说 Window 线程调度程序使用“公平”算法,例如具有相同优先级的所有线程都同样可能被调度?如果是这样,对于相同优先级的线程,哪个优先调度?顺序是随机的还是以某种方式确定的?【参考方案2】:

以上所有内容都是准确的,但如果您担心 50 个线程进程会占用所有 CPU,那么您可以采取一些技术来确保没有单个进程会占用 CPU。

恕我直言,最好的方法是使用job objects 来管理进程的使用。首先调用CreateJobObject,然后调用SetInformationJobObject 来限制作业对象中进程的最大CPU 使用率,然后AssignProcessToJobObject 将具有50 个线程的进程分配给作业对象。然后,您可以让操作系统确保 50 个线程的进程不会消耗过多的 CPU 时间。

【讨论】:

如果有可供最终用户使用的工具,那对 Windows 来说将是一个巨大的胜利。 有,有点。启动任务管理器,右键单击一个进程并选择“设置关联”。这允许您将单个线程分配给特定的 CPU。这不是一回事,但很接近。【参考方案3】:

调度的单位是一个线程,而不是一个进程,所以一个有 50 个线程的进程,都在一个紧密的循环中,将比只有一个线程的进程获得更多的 cpu,前提是所有线程都运行在相同的优先级。这通常不是问题,因为系统中的大多数线程都不处于可运行状态并且不会被调度;他们正在等待 I/O,等待用户的输入,等等。

Windows Internals 是一本了解 Windows 线程调度程序的好书。

【讨论】:

【参考方案4】:

这取决于线程的行为。一般来说,线程数的差异为 50 : 1,是的,具有更多线程的应用程序将获得更多时间。但是,windows 也使用动态线程优先级,这可以在一定程度上改变这一点。此处描述了动态线程优先级:

https://web.archive.org/web/20130312225716/http://support.microsoft.com/kb/109228

相关摘录:

线程的基本优先级是进行这些向上调整的基本级别。线程的当前优先级称为其动态优先级。在其时间片结束之前产生的交互式线程将倾向于从其基本优先级向上调整优先级。不屈服的计算绑定线程消耗了它们的整个时间片,它们的优先级往往会降低,但不会低于基本级别。这种安排通常称为启发式调度。它提供了更好的交互性能,并倾向于减少“CPU hog”线程对系统的影响。

【讨论】:

【参考方案5】:

有一个本地“高级”设置据称可用于稍微调整日程安排,以支持具有焦点的应用程序。使用“服务”设置,没有偏好。在以前的 Windows 版本中,此设置过去比“具有焦点的应用程序”(稍微偏爱具有焦点的应用程序)和“服务”(所有同等权重)更加精细

因为这可以由目标机器上的用户设置,所以它似乎要求悲伤取决于这个设置......

【讨论】:

以上是关于Win32线程调度的主要内容,如果未能解决你的问题,请参考以下文章

RT-Thread内核线程调度算法(基于位图的线程调度算法)

WPF怎么跨线程访问UI控件

cuda为啥要开启32倍数的线程

进程与线程的问题

App Engine 调度程序何时使用新线程与新实例?

在 Objective C 中调度块的执行