谁调度线程?
Who schedules threads?
我有一个关于调度线程的问题。一方面,我了解到线程在 Linux 中被调度和视为进程,这意味着它们像使用传统方法的任何其他进程一样被调度。 (例如 linux 中的完全公平调度器)
另一方面,我也知道 CPU 也可能使用 Switch on Event 或 Fine-grain 等方法在线程之间切换。例如,在缓存未命中事件中,CPU 切换线程。但是如果调度器不想切换线程呢?他们如何就一项行动达成一致?
我真的很困惑两者:谁安排线程? OS 或 CPU?
非常感谢:)
OS 处理就绪线程(需要 CPU 的线程)到内核的调度和分派,以与管理其他资源类似的方式管理 CPU 执行。缓存未命中不是换出线程的理由。页面错误,即所需页面根本没有加载到 RAM 中,可能会导致线程被阻塞,直到页面从磁盘加载。内存管理硬件通过向处理页面错误的 OS 驱动程序生成硬件中断来实现这一点。
答案都是。
发生的事情确实相当简单:在支持每个内核多线程的CPU上(例如,具有超线程的英特尔)出现CPU OS 具有一定数量的虚拟内核。例如,Intel i7 有 4 个实际内核,但看起来 OS 像 8 个内核。
OS 将 8 个线程调度到这 8 个(虚拟)内核上。当需要进行任务切换时,OS 的调度程序会查看线程并找到最适合 运行 的 8 个线程(考虑线程优先级、时间等因素自从它们上次 运行,等等)
CPU只有 4 个真正的内核,但是这些内核支持同时执行多条指令(并且在没有依赖项的情况下是乱序的)。传入的指令被解码并扔进 "pool"。每个时钟周期,CPU 都会尝试在该池中找到一些不依赖于先前指令结果的指令。
如果每个内核有多个线程,基本上每个实际内核都有两个输入流可以放入 "pool" 指令中,它可能能够在给定的时钟周期内执行。每个时钟周期它仍然从该池中查找不依赖于尚未完成执行的先前指令的结果的指令。如果它找到一些,它会将它们放入执行单元并执行它们。唯一的主要变化是每条指令现在都需要附加某种标签来指定 "virtual core" 将用于将结果存储到——也就是说,两个线程中的每一个都有(例如)自己的一组寄存器,并且来自每个线程的指令必须写入该虚拟核心的寄存器。
但是,CPU 有可能支持某种程度的线程优先级,这样(例如)如果可用指令池包括来自两个输入线程(或所有 N 个输入线程)的一些指令,如果有两个以上)在任何给定的时钟周期中,它会更愿意选择来自一个线程的指令而不是来自另一个线程的指令。这可以是绝对的,所以它 运行 线程 A 尽可能快,而线程 B 只有与周期 A 不能使用,或者它可以是 "milder" 偏好,比如试图维护一个2:1 执行指令的比率(或者,当然,基本上是首选的任何其他比率)。
当然还有其他设置优先级的方式(比如划分执行资源),但是大体思路是一样的。
像这样了解共享核心的 OS 也可以修改其调度以适应,例如如果线程具有更高的优先级,则只在一对核心上调度一个线程。
我有一个关于调度线程的问题。一方面,我了解到线程在 Linux 中被调度和视为进程,这意味着它们像使用传统方法的任何其他进程一样被调度。 (例如 linux 中的完全公平调度器)
另一方面,我也知道 CPU 也可能使用 Switch on Event 或 Fine-grain 等方法在线程之间切换。例如,在缓存未命中事件中,CPU 切换线程。但是如果调度器不想切换线程呢?他们如何就一项行动达成一致?
我真的很困惑两者:谁安排线程? OS 或 CPU?
非常感谢:)
OS 处理就绪线程(需要 CPU 的线程)到内核的调度和分派,以与管理其他资源类似的方式管理 CPU 执行。缓存未命中不是换出线程的理由。页面错误,即所需页面根本没有加载到 RAM 中,可能会导致线程被阻塞,直到页面从磁盘加载。内存管理硬件通过向处理页面错误的 OS 驱动程序生成硬件中断来实现这一点。
答案都是。
发生的事情确实相当简单:在支持每个内核多线程的CPU上(例如,具有超线程的英特尔)出现CPU OS 具有一定数量的虚拟内核。例如,Intel i7 有 4 个实际内核,但看起来 OS 像 8 个内核。
OS 将 8 个线程调度到这 8 个(虚拟)内核上。当需要进行任务切换时,OS 的调度程序会查看线程并找到最适合 运行 的 8 个线程(考虑线程优先级、时间等因素自从它们上次 运行,等等)
CPU只有 4 个真正的内核,但是这些内核支持同时执行多条指令(并且在没有依赖项的情况下是乱序的)。传入的指令被解码并扔进 "pool"。每个时钟周期,CPU 都会尝试在该池中找到一些不依赖于先前指令结果的指令。
如果每个内核有多个线程,基本上每个实际内核都有两个输入流可以放入 "pool" 指令中,它可能能够在给定的时钟周期内执行。每个时钟周期它仍然从该池中查找不依赖于尚未完成执行的先前指令的结果的指令。如果它找到一些,它会将它们放入执行单元并执行它们。唯一的主要变化是每条指令现在都需要附加某种标签来指定 "virtual core" 将用于将结果存储到——也就是说,两个线程中的每一个都有(例如)自己的一组寄存器,并且来自每个线程的指令必须写入该虚拟核心的寄存器。
但是,CPU 有可能支持某种程度的线程优先级,这样(例如)如果可用指令池包括来自两个输入线程(或所有 N 个输入线程)的一些指令,如果有两个以上)在任何给定的时钟周期中,它会更愿意选择来自一个线程的指令而不是来自另一个线程的指令。这可以是绝对的,所以它 运行 线程 A 尽可能快,而线程 B 只有与周期 A 不能使用,或者它可以是 "milder" 偏好,比如试图维护一个2:1 执行指令的比率(或者,当然,基本上是首选的任何其他比率)。
当然还有其他设置优先级的方式(比如划分执行资源),但是大体思路是一样的。
像这样了解共享核心的 OS 也可以修改其调度以适应,例如如果线程具有更高的优先级,则只在一对核心上调度一个线程。