try ai
科普
编辑
分享
反馈
  • 处理器共享:普适的公平原则

处理器共享:普适的公平原则

SciencePedia玻尔百科
核心要点
  • 处理器共享是一种理想化模型,其中 CPU 在所有任务之间完美划分,确保了可预测且成比例的减速。
  • 现实世界的操作系统使用轮询(RR)和加权公平队列(WFQ)等调度器来逼近这一理想,以平衡公平性与效率。
  • 护航效应——即短的交互式任务被卡在长任务之后——说明了公平、抢占式调度的关键需求。
  • 公平共享原则是一个普适概念,不仅适用于 CPU,也适用于管理网络带宽、存储 IOPS 和 GPU 资源。

引言

在现代计算世界中,设备在数量有限的处理器上持续进行着杂耍般的表演,同时处理着无数任务。这种并行执行的幻象并非魔法,而是一项核心计算机科学原则的结果:处理器共享。一个系统如何在其各种竞争性需求——从简单的鼠标点击到复杂的视频渲染——之间公平而高效地分配其处理能力?这个问题代表了系统设计中的一个根本性挑战,不公平的分配可能导致性能迟缓和令人沮丧的用户体验,这一问题被“护航效应”形象地概括。本文深入探讨处理器共享的优雅理论和强大应用,以回答此问题。“原理与机制”部分将介绍理想化的处理器共享模型,并探讨其实际近似方法,如轮询和加权公平队列,揭示在公平性与现实约束之间取得平衡的复杂艺术。随后的“应用与跨学科联系”部分将展示这一原则的普适性,说明它如何为管理从云服务器和网络路由器到存储设备乃至人类系统等不同领域的资源提供统一的解决方案。

原理与机制

在任何现代计算设备的核心,都存在着一个深刻的幻象。一个在任何给定微秒内只能做一件事的单一处理器,却能巧妙地同时处理数十甚至数千个需求。它渲染你的视频,接收你的电子邮件,更新你的时钟,并响应你的鼠标点击,所有这些似乎都是同时发生的。这场宏大的表演之所以成为可能,得益于计算机科学中最基本、最优雅的概念之一:​​处理器共享​​。

我们对这个主题的探索并非始于现实世界调度器的繁杂细节,而是从一个优美、理想化的抽象开始。让我们想象一个神奇的处理器。

完美公平的理想:处理器共享

想象一个 CPU,它不是一个单一、不可分割的单元,而是一种可以完美、即时分割的流体资源。如果有两个任务需要运行,这个神奇的处理器会把自己一分为二,精确地将 50% 的能力分配给每个任务。如果第三个任务到达,处理器会立即重新配置为三等份。这就是​​处理器共享(Processor Sharing, PS)​​模型的精髓。

在 PS 的世界里,公平是绝对的。如果有 nnn 个任务请求服务,每个任务都会获得恰好为 1/n1/n1/n 的瞬时服务速率。这种完美划分的结果是显著的可预测性。一个需要 sss 秒计算才能完成的任务,在有其他 n−1n-1n−1 个任务存在的情况下,将花费恰好 T=s×nT = s \times nT=s×n 秒的墙上时钟时间来完成。对于每个任务而言,其减速是成比例且完全相同的。这就是柏拉图式的公平理想:每个任务都受到同等对待,其完成时间仅因同伴的存在而延迟。

从理想到现实:近似的艺术

当然,真实的处理器并非由神奇的、可分割的流体制成。它们是具体的,一次只执行来自一个任务的一条指令。那么,我们如何创造出 PS 的幻象呢?最简单、最直观的方法是让任务轮流执行。这被称为​​轮询(Round-Robin, RR)​​调度。

处理器将自身专用于单个任务一小段时间,这段时间称为​​时间片​​(time quantum, qqq)。当时间片用尽时,处理器停止,保存该任务的状态,然后转向队列中的下一个任务。通过在任务间快速循环,RR 创造出一种强大的同步进展的幻象。

当然,这种近似并非完美。与理想 PS 的平滑、连续服务不同,RR 下任务的进展是一系列短暂的活动爆发,随后是等待期。这种“断续性”代表了对理想状态的偏离。我们甚至可以量化这种不完美性。一个任务在 RR 下获得的服务与在理想 PS 下本应获得的服务之间的最大差异,被称为​​切片粒度误差​​。这个误差可以用一个极其简洁的表达式来表示:ϵ(q)=q(1−1/n)\epsilon(q) = q(1 - 1/n)ϵ(q)=q(1−1/n)。这个公式告诉我们一个深刻的道理:误差与我们的时间片大小 qqq 成正比。随着我们让时间片越来越小,我们断续的近似就越来越接近处理器共享的平滑理想。在极限情况下,当 qqq 趋近于零时,轮询调度 就成为 处理器共享。

公平为何重要:护航效应

对公平的追求并不仅仅是学术探讨。一个不公平的调度器会导致系统感觉迟钝、无响应且令人沮丧。对此最经典的例证就是​​护航效应​​。

想象一个简单的、非抢占式的调度器,如​​先到先服务(First-Come, First-Served, FCFS)​​。它就像杂货店的结账队伍:谁先排队谁就先得到服务,并且服务会持续到完成。现在,设想这样一个场景:一个大型的、CPU 密集型任务(比如一个 20 毫秒的视频编码作业)恰好在三个小型的、交互式任务(例如来自你的网页浏览器的三个 1 毫秒请求)之前几毫秒到达。

在 FCFS 下,这些小巧、敏捷的任务被困在那个庞大、缓慢移动的任务后面的“护航队列”中。它们已经准备好运行,并且几乎可以瞬间完成,但它们被迫等待整整 20 毫秒,直到那个大作业完成。这些短任务的平均响应时间变得极其漫长。

现在,考虑在处理器共享规则下的相同场景。小作业到达的那一刻,处理器就在所有四个任务之间共享。每个任务获得 CPU 1/4 的能力。那些只需要 1 毫秒工作的小作业,现在仅需 4 毫秒的墙上时钟时间即可完成。系统感觉响应迅速、快捷。护航队列被彻底消除了。这就是抢占和公平共享的力量。它优先保证了短任务的响应性——这正是让系统感觉具有交互性的关键——同时并未显著损害长任务的吞吐量。即便如此,像 RR 这样的实际实现仍然可能因不幸的时机而受影响,例如一个 I/O 密集型任务反复在唤醒时发现自己排在队尾,从而产生一种更微妙的护航效应。这推动了我们接下来将看到的更复杂的机制的发展。

超越平等:加权公平与虚拟时间

到目前为止,我们对公平的定义是“人人享有平等的份额”。但如果某些任务比其他任务更重要呢?一个实时视频流应当比后台文件索引服务拥有更高的优先级。为了处理这个问题,我们将处理器共享推广为​​通用处理器共享(Generalized Processor Sharing, GPS)​​,通常通过一种名为​​加权公平队列(Weighted Fair Queueing, WFQ)​​的算法来实现。

这个想法很简单:我们不再给予相等的份额,而是为每个任务 iii 分配一个​​权重​​ wiw_iwi​。处理器的能力随后按这些权重成比例地划分。一个权重为 wA=2w_A = 2wA​=2 的任务将获得一个权重为 wB=1w_B = 1wB​=1 的任务两倍的服务速率。

这就提出了一个新问题:调度器如何优雅地执行这些任意比例,特别是当任务不断启动、停止或因 I/O 而阻塞时?答案是调度理论中最优美的机制之一:​​虚拟时间​​。

想象一下,每个任务都在其自己的私有虚拟处理器上运行。这个虚拟处理器的速度由任务的权重决定。高权重的任务获得一个快速的虚拟时钟,而低权重的任务则获得一个慢速时钟。任务的虚拟运行时间仅在它实际使用真实 CPU 时才会增加。调度器只有一个简单的规则:​​始终运行虚拟运行时间最小的任务​​。

想一想这意味着什么。虚拟运行时间最低的任务,是那个*相对于其重要性(权重)*在其进度上“落后最远”的任务。通过总是将 CPU 交给最“应得”的任务,调度器自动确保,随着时间的推移,每个任务都能获得其成比例的 CPU 份额。如果一个任务因 I/O 而阻塞,它的虚拟时钟会冻结。当它唤醒时,它的虚拟运行时间很可能远低于那些持续运行的 CPU 密集型任务。调度器会自然地偏爱它,让它得以“赶上”。这种机制不仅公平,而且异常简单和稳健,构成了像 Linux 完全公平调度器(Completely Fair Scheduler, CFS)这样的现代调度器的基础。

共享的普适原则

公平共享的原则是如此强大,以至于其应用远远超出了在 CPU 上调度任务的范畴。它是管理计算机系统中几乎任何共享资源的通用解决方案。

  • ​​多处理器负载均衡:​​在一个拥有多个 CPU 核心的系统上,一个新任务应该放在哪里?一个简单的做法可能是将其放在分配任务最少的核心上。但正如我们所见,一些任务是 CPU 密集的,而另一些则经常因等待 I/O 而阻塞。一个真正公平的方法是将新任务放置在具有最低可运行任务期望数量的核心上。这是 PS 原则的直接应用:最小化竞争以最小化延迟。

  • ​​内存控制器:​​内存总线是另一个关键的共享资源。现代内存控制器可以使用 WFQ 来管理来自不同应用程序的请求。这确保了高优先级的、对延迟敏感的应用程序(如视频游戏)能获得其保证的内存带宽份额,防止它被低优先级的、消耗大量带宽的后台备份进程饿死。如果高优先级应用程序没有用完其全部份额,GPS 原则确保这部分空闲容量会自动且公平地重新分配给其他活动应用程序。

  • ​​网络服务器:​​一个事件驱动的网络服务器可能要处理数千个并发连接。如果它对传入事件使用简单的 FIFO 队列,少数几个非常活跃的连接可能会淹没队列,使所有其他连接饿死。通过使用像赤字轮询(Deficit Round Robin, DRR)这样的公平调度器(它近似于 GPS),服务器可以保证每个连接都获得公平的处理时间份额。这不仅确保了所有用户的响应性,而且对系统稳定性至关重要,防止了低流量套接字的队列无限制地增长。

但“公平”究竟意味着什么?

最后,值得注意的是,处理器共享的“成比例减速”式公平并非唯一定义。对于交互式系统,我们通常希望不惜一切代价优先处理短作业。像​​最短剩余时间优先(Shortest Remaining Time First, SRTF)​​这样的策略正是这样做的,它总是运行最接近完成的作业。

我们可以用一个名为​​减速因子​​的指标来衡量这一点,它被定义为一个作业的总周转时间除以其服务时间。理想的减速因子是 111。在 SRTF 下,短作业通常能实现非常接近 1 的减速因子,这意味着它们几乎没有被延迟。这样做的代价是长作业,它们会被抢占,并可能经历非常高的减速。相比之下,PS 给予所有作业一个更统一但更高的减速因子。

没有哪种策略是普遍“更好”的。SRTF 优化了短任务的响应性,这与人类对性能的感知相符。处理器共享则优化了一种更可预测、更平等的公平概念。它们之间的选择是一种哲学的选择,揭示了即使在算法的精确世界里,也存在着不同价值观和优先级的空间。

应用与跨学科联系

在我们完成了对处理器共享优雅原理的探索之后,你可能会留下一个挥之不去的问题:这仅仅是一个优美的数学抽象,一个物理学家对完美流式计算机的梦想吗?还是说这个想法真的在现实世界中出现过?答案是响亮的“是”,而且它在何处以及如何出现的故事,可能比理论本身更加引人入胜。公平共享原则是一个惊人地普适的概念,像一把万能钥匙,解开了那些乍一看似乎彼此毫无关联领域中的问题。

让我们从这个概念的最初家园开始:中央处理器(CPU)。在计算的早期,一台巨大的机器可能服务于整个大学或公司。挑战在于如何让几十个人同时使用它,而没有人感觉自己等了太久。这催生了分时系统,即我们笔记本电脑和手机上操作系统的直系祖先。处理器共享不仅仅是这些系统的近似;它正是其设计哲学的灵魂。想象一下,你正在为一家公司管理一台终端服务器。你签署了一份服务水平协议(SLA),承诺任何用户命令的平均响应时间将保持在,比如说,0.150.150.15 秒以下。随着越来越多的员工登录,服务器变得越来越忙,速度也越来越慢。你如何知道何时停止接纳新用户以避免违背承诺?

使用处理器共享模型,我们可以精确地回答这个问题。我们知道,对于一个服务容量为 μ\muμ、总请求到达率为 λ\lambdaλ 的系统,其平均响应时间 RRR 的公式非常简洁:R=1/(μ−λ)R = 1/(\mu - \lambda)R=1/(μ−λ)。通过将每个用户会话视为一个请求源,我们可以预测任何数量的活跃用户下的响应时间。一个准入控制器可以利用这个公式来计算如果再接纳一个用户,响应时间将会是多少。如果那个预测时间超过了 SLA 的红线,新用户的会话就会被礼貌地拒绝。这不仅仅是一个假设性的练习;它是容量规划和服务质量工程的基本原则,正是它让我们的云服务保持敏捷和响应迅速。

这种共享 CPU 能力的想法自然地延伸到了云计算和大规模数据中心的现代。如今,一台物理服务器可能托管着几十个虚拟机或容器,每个都在运行不同的应用程序。一个容器可能在运行一个对延迟敏感的 Web 服务器,而另一个则在通宵处理一个庞大的批处理作业。你如何确保 Web 服务器总有足够的能力即时响应用户,同时还让批处理作业使用所有剩余资源?像 Linux 这样的现代操作系统通过“控制组”(cgroups)提供了这一思想的直接实现。你简直可以告诉操作系统:“给 Web 服务器的组分配至少 2.1672.1672.167 个核心的算力,批处理作业可以用剩下的。”然后,操作系统的调度器,作为加权处理器共享的一个实际近似,会执行这种划分,保证关键应用的性能,同时最大化昂贵硬件的利用率。

但“公平”共享到底意味着什么,尤其是当不同用户的需求大相径庭时?想象一个多人游戏服务器。一些玩家可能正在进行激烈的、CPU 消耗巨大的交火,而另一些玩家则在村庄里悠闲地闲逛。平均分配 CPU 会是一种浪费;空闲的玩家并不需要他们的全部份额。一个真正的处理器共享系统会自动处理这种情况。它为每个玩家提供一个平等的份额,但如果某个玩家没有使用它,那部分空闲容量会立即公平地重新分配给确实需要它的玩家。这个原则被称为最大最小公平(max-min fairness)。我们甚至可以使用像 Jain 公平指数这样的指标来量化一个分配的公平程度,为我们提供一个数学工具来理性分析共享系统中的用户体验。

从理想流体到颗粒现实

当然,现实世界从来不像我们理想的处理器共享流体模型那样平滑。一个真实的 CPU 调度器并不会无限小地划分其注意力。相反,它以离散的时间片(或称“quanta”)来运作。它让一个进程运行几毫秒,然后切换到下一个,依此类推。正是在这里,优美的理论与工程上的权衡相遇了。

这种轮询方法是处理器共享的一种实际实现,但它是有代价的:上下文切换。每当调度器停止一个进程并启动另一个时,它都会在开销上浪费掉一小部分时间 sss。如果你有 mmm 个进程,一个完整周期给每个进程一个时间片需要的时间是 ∑qi+m⋅s\sum q_i + m \cdot s∑qi​+m⋅s。完成的总有用功仅仅是 ∑qi\sum q_i∑qi​。CPU 用于有用功的时间比例——即其效率——因此是 (∑qi)/(∑qi+m⋅s)(\sum q_i) / (\sum q_i + m \cdot s)(∑qi​)/(∑qi​+m⋅s)。

在这里我们看到了一个经典的困境。如果我们为了更好地近似理想的“流体”模型而把时间片设得非常小,那么开销项 m⋅sm \cdot sm⋅s 就会开始占主导地位,CPU 将所有时间都花在切换上,而没有做任何有用的工作!相反,如果我们把时间片设得非常大,开销就变得可以忽略不计,效率接近 100%,但系统会感觉迟钝和无响应,因为每个进程都必须等待很长时间才能轮到自己。调度器设计的艺术就在于驾驭这种权衡,而加权轮询调度器通过根据进程权重分配不同的时间片长度来做到这一点,为实现加权处理器共享的目标提供了一条切实可行的路径。公平性得以保留,但代价是效率的损失。为了实现这一点,人们设计了不同的算法,从像步幅调度(Stride Scheduling)这样即使在短期内也能保证近乎完美公平的确定性算法,到像彩票调度(Lottery Scheduling)这样更简单、仅在长期平均意义上保证公平的概率性算法。

统一原则:超越 CPU 的共享

故事在这里变得真正深刻起来。公平共享资源的问题是普适的。我们为 CPU 开发的相同数学原理,几乎无需修改,就适用于完全不同的领域。

想一想网络路由器。它有来自不同计算机的大量数据包涌入,所有这些数据包都在竞争通过一根电缆发送出去。一个 CPU 上的进程请求一片时间,就像一个数据流请求一片带宽一样。CPU 的总处理能力 CCC 类似于网络链路的容量。CPU 进程的不可抢占的执行突发,就像一个不可分割的数据包。为这个网络问题开发的调度算法,称为加权公平队列(Weighted Fair Queuing, WFQ),在数学上等同于我们一直在研究的通用处理器共享(Generalized Processor Sharing, GPS)。两个系统中的公平性误差——即与理想流体模型的偏差——都受到完全相同事物的限制:最大“不可分割”工作块的大小,无论是在 CPU 上的不可抢占内核段,还是网络上的一个大数据包。这是一个惊人的智识统一的例子。两个不同的领域,操作系统和计算机网络,独立地为同一个基本问题找到了同样优美的解决方案。

这种普适性并未止步于此。

  • ​​存储设备:​​ 一块硬盘或 SSD 每秒只能执行一定数量的输入/输出操作(IOPS)。你如何在一系列不同的应用程序之间共享这个稀缺资源?通过使用基于 WFQ 的 I/O 调度器,你可以为不同类别的请求分配权重(例如,为数据库事务分配高优先级,为后台文件索引器分配低优先级),并为它们提供可预测的、差异化的延迟。同样的原则也允许存储系统在一个高优先级的用户工作负载和一个必要但资源密集的后台任务(如在 RAID 阵列中重建一个失败的磁盘)之间进行仔细的平衡 [@problem_d:3675068]。
  • ​​图形处理单元(GPUs):​​ 现代 GPU 是并行处理的怪兽,但它们运行的任务(称为内核)通常是不可抢占的。如果多个应用程序提交内核,GPU 如何决定下一步运行什么?再一次,比例共享的原则适用。调度器的公平性可以被分析,其与理想模型的偏差受限于最长可能内核的运行时间——我们那个不可分割的工作块再次出现!。

公平的隐喻

处理器共享思想的力量如此之大,以至于它甚至为思考人类系统中的公平性提供了一个强大的隐喻。想象一个学术会议,它同时接收来自资深、知名研究人员和初级、崭露头角的年轻研究人员的论文。一个“严格优先级”系统可能会决定首先评审所有资深研究员的论文。如果资深研究员的投稿数量足够大,初级研究员的论文可能永远也得不到评审——它们被“饿死”了,无法获得资源(评审员的时间)。这与计算机中低优先级进程被高优先级进程饿死的情况完全相同。

那么,如果会议实施一种“加权公平”政策呢?例如,它可以设置权重 ws=3w_s=3ws​=3 和 wj=1w_j=1wj​=1,确保每评审三篇资深研究员的论文,就有一篇初级研究员的论文得到评审。这完全消除了饿死现象;每个初级研究员的投稿都保证能取得进展。然而,这并不能凭空创造出更多的评审员。如果总投稿率超过了总评审能力,论文的“队列”仍然会无限增长,系统将变得“不稳定”。WFQ 保证了公平性并防止了饿死,但它无法克服根本性的超载问题。

从 CPU 旋转的核心到互联网繁忙的流量,从硬盘的呼啸到人类事业的抽象流程,比例共享这个简单而优雅的思想带来了秩序、可预测性和公平。它证明了一个深刻的科学原理不仅仅是一个问题的解决方案,更是一个镜头,通过它我们可以理解世界上一个惊人广阔部分的结构。