【操作系统导论】比例份额调度

本文介绍一种 比例份额(proportional-share) 调度程序,也称为 公平份额(fair-share)

彩票调度

简介

彩票调度 的基本思想:

  • 每隔一段时间,都会举行一次彩票抽奖,以确定接下来应该运行哪个进程;

  • 越是应该频繁运行的进程,越是应该拥有更多地赢得彩票的机会。

关键在于如何按比例分配 CPU。

利用了 随机性(randomness),具有以下优势:

  • 随机方法很轻量,几乎不需要记录任何状态;

  • 随机方法很快,只要能很快地产生随机数,做出决策也就很快;

  • 随机方法常常可以避免奇怪的边角情况,较传统的算法可能在处理这些情况时遇到麻烦。

彩票机制

*彩票数(ticket)*代表进程占有某个资源的份额:一个进程拥有的彩票数占总数的百分比,就是它占有资源的份额。

假设有两个进程 A 和 B,A 拥有 75 张彩票,B 拥有 25 张;我们希望 A 占用 75%的 CPU 时间,而 B 占用 25%。

彩票调度程序输出的中奖彩票:

在这里插入图片描述

对应的调度结果:

在这里插入图片描述

上面例子中,工作 B 运行了 20 个时间片中的 4 个,只是占了 20%,而不是期望的 25%。

但是,如果这两个工作运行得时间越长,它们得到的 CPU 时间比例就会越接近期望

彩票调度还提供了一些机制,以不同且有效的方式来调度彩票。

  • 彩票货币 (ticket currency)

用户可以自定义他们自己的货币, 并分给自己的不同工作;之后操作系统再将这种货币兑换为全局彩票。

假设用户 A 和用户 B 每人拥有 100 张全局彩票。用户 A 有两个工作 A1 和 A2,分给每个工作 500 个货币。用户 B 只运行一个工作,给它 10 个货币。

操作系统将进行兑换,将 A1 和 A2 拥有的 A 的货币 500 个,兑换成全局彩票 50 张;将 B1 的 10 个货币兑换成 100 张全局彩票;然后对 200 张全局彩票进行抽奖,决定哪个工作运行。

在这里插入图片描述

  • 彩票转让 (ticket transfer)

通过转让,一个进程可以临时将自己的彩票交给另一个进程。

这种机制在 C/S 交互的场景中尤其有用,客户端进程向服务端发送消息,请求其按自己的需求执行工作,为了加速服务端的执行, 客户端可以将自己的彩票转让给服务端,从而尽可能加速服务端执行自己请求的速度。服务端执行结束后会将这部分彩票归还给客户端。

  • 彩票通胀 (ticket inflation)

利用通胀,一个进程可以临时提升或降低自己拥有的彩票数量。

当然在竞争环境中,进程之间互相不信任,这种机制就没什么意义。一个贪婪的进程可能给自己非常多的彩票,从而接管机器。

但是,通胀可以用于进程之间相互信任的环境。在这种情况下,如果一个进程知道它需要更多 CPU 时间,就可以增加自己的彩票,从而将自己的需求告知操作系统,这一切不需要与任何其他进程通信。

具体实现

彩票调度的实现非常简单,只需要 一个不错的随机数生成器来选择中奖彩票一个记录系统中所有进程的数据结构(一个列表),以及所有彩票的总数。

假定用列表记录进程,下面的例子中有 A、B、C 这 3 个进程,每个进程有一定数量的彩票。

在这里插入图片描述

代码实现如下:

// counter: used to track if we've found the winner yet 
int counter = 0;

// get a value between 0 and the total of tickets 
int winner = getrandom(0, totaltickets);

// current: use this to walk through the list of jobs 
node_t *current = head;

// loop until the sum of ticket values is > the winner 
while (current) {
    counter = counter + current->tickets; 
    if (counter > winner)
        break;
}

// now 'current' is the winner: schedule it...

如果要让这个过程更有效率,可以将列表项按照彩票数递减排序。

算法分析

我们知道彩票调度是一种“公平份额”调度算法,那么它的公平性如何呢?

假设有两个互相竞争的工作,每个工作都有相 100 张彩票,以及相同的运行时间 R。

我们希望两个工作大约同时完成,但由于彩票调度的随机性,一个工作可能先于另一个完成。

为了量化这种区别,我们定义一个不公平指标 U,将两个工作完成时刻相除得到 U 的值。

在这里插入图片描述

可以看出,当工作执行时间很短时,公平性非常糟糕。只有当工作执行非常多的时间片时,彩票调度算法才能得到期望的结果。

还有一个问题没有提到,那就是如何为工作分配彩票?

这是一个非常棘手的问题,系统的运行严重依赖于彩票的分配。

假设用户自己知道如何分配,则可以分给每个用户一定量的彩票,由用户自主分配给其工作。

然而还是没有具体的分配策略。对于给定的一组工作,彩票分配的问题依然没有最佳答案。

步长调度

简介

虽然随机方式可以使得调度程序的实现简单,但偶尔并不能产生正确的比例,尤其在工作运行时间很短的情况下。

出于这个原因,Waldspurger 提出 步长调度 (stride scheduling), 确定性的公平份额算法。

步长机制

步长调度的基本思想:

系统中的每个工作都有自己的 步长 (stride),与票数值成反比。比如 A、B、C 这 3 个工作的票数分别是 100、50 和 250,则可以用一个「大数」分别除以它们的票数来获得进程的步长。

如果用 10000 除以这些票数值,得到了 3 个进程的步长分别为 100、200 和 40。

每次进程运行后,会让它的计数器「行程值 (pass) 」增加它的步长,记录它的总体进展。

调度程序根据进程的步长及行程值来确定调度哪个进程:

在调度时,选择目前拥有最小行程值的进程,并在运行之后将该进程的行程值增加一个步长。

current = remove_min(queue);       // pick client with minimum pass
schedule(current);                 // use resource for quantum
current->pass += current->stride;  // compute next pass using stride
insert(queue, current);            // put back into the queue

在上面例子中,3 个进程 (A、B、C) 的步长值分别为 100、200 和 40,初始行程值都为 0。因此,最初,所有进程都可能被选择执行。假设先执行 A,再执行 B,执行过程如下:

在这里插入图片描述

可以看出,C 运行了 5 次、A 是 2 次,B 是 1 次,正好是票数的比例——200、100 和 50。

算法分析

  1. 步长调度需要全局状态 (行程值)

彩票调度不需要对每个进程记录全局状态,只需要用新进程的票数更新全局的总票数即可;

  1. 选择步长仍然是一个棘手的问题

步长太小可能导致进程频繁地被切换,增加上下文切换的开销;步长太大可能导致某些进程长时间占用CPU而不释放,影响系统的响应性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Skylar Lin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值