处理器调度:原理

处理器调度:原理

2024 南京大学《操作系统:设计与实现》
处理器调度:原理

资源调度 (分配) 策略:复杂且关键的问题

人类世界中的调度

  • 学校预算 10,000,000 科研经费,怎么分给院系?
  • 发改委下拨 1,000,000,000,000 经费,怎么分给全中国?
  • 恒大总负债 2,400,000,000,000 元,怎么解决?

计算机世界中的调度

  • 队列中有 100 个提交,应该如何分配给评测机?
  • 队列中有 100 个批处理任务,按照什么顺序执行?
  • 到下次时钟中断有 10,000,000 个时钟周期,应该分配给哪个进程?
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

调度策略的设计空间

(人类的本质)

  • 建模
    • “系统是什么”
    • “过去发生了什么”
    • “我们能对系统做什么”
  • 预测
    • 在假想的 “做什么” 基础上预测未来系统的行为
  • 决策
    • 评估预测结果,作出对系统最有利的选择
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

策略很难设计?

再加一层机制:“niceness”

  • 至于谁更 nice,由管理员/另一个程序决定
  • 人类世界中也有类似的机制 (“985”, “211”, v.s. “双非”)

center

2024 南京大学《操作系统:设计与实现》
处理器调度:原理

UNIX Niceness

-20 .. 19 的整数,越 nice 越让别人得到 CPU

  • -20: 极坏; most favorable to the process
  • 19: 极好; least favorable to the process

基于 “好坏” (优先级) 的调度策略

  • RTOS: 坏人躺下好人才能上
    • 好人流下了悔恨的泪水
    • Linux: 10 nice ≈ CPU 资源获得率相差 10 倍
taskset -c 3 nice -n 19 yes > /dev/null &
taskset -c 3 nice -n  9 yes > /dev/null &
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

如果 Nice 值相同?

那就公平分享 CPU 吧 (Round-Robin)

  • Round-Robin

遇到的麻烦

  • 交互式的 Vim,单线程
  • 纯粹计算的 mandelbrot.c, 32 个线程
    • Vim 花 0.1ms 处理完输入就继续等待了
    • 主动让出 CPU,进入 round-robin
    • 但此时 Vim 收到了输入……
      • (你们会在 L2 里遇到这样的问题)
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

策略:动态优先级 (MLFQ)

不会设置优先级?让系统自动设定!

  • 用完时间片 → 坏人 (请 Mandelbrot 变得 “更好”)
  • 让出 CPU (I/O) → 好人 (Vim 可以变得更坏)
    • 1960s: breakthrough!
    • 2020s: 对很多负载都 “欠考虑”

center

2024 南京大学《操作系统:设计与实现》
处理器调度:原理

策略:Complete Fair Scheduling (CFS)

试图去模拟一个 “Ideal Multi-Tasking CPU”:

  • “Ideal multi-tasking CPU” is a (non-existent :-)) CPU that has 100% physical power and which can run each task at precise equal speed, in parallel, each at 1/n. For example: if there are 2 tasks running, then it runs each at 50% physical power — i.e., actually in parallel.

“让系统里的所有进程尽可能公平地共享处理器”

  • 为每个进程记录精确的运行时间
  • 中断/异常发生后,切换到运行时间最少的进程执行
    • 下次中断/异常后,当前进程的可能就不是最小的了
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

CFS: 实现优先级

操作系统具有对时钟中断的 “绝对控制”

  • 每人执行 1ms,但好人的钟快一些,坏人的钟慢一些
    • vruntime (virtual runtime)
    • vrt[i] / vrt[j] 的增加比例 = wt[j] / wt[i]
const int sched_prio_to_weight[40] = {
  /* -20 */ 88761, 71755, 56483, 46273, 36291,
  /* -15 */ 29154, 23254, 18705, 14949, 11916,
  /* -10 */  9548,  7620,  6100,  4904,  3906,
  /*  -5 */  3121,  2501,  1991,  1586,  1277,
  /*   0 */  1024,   820,   655,   526,   423,
  /*   5 */   335,   272,   215,   172,   137,
  /*  10 */   110,    87,    70,    56,    45,
  /*  15 */    36,    29,    23,    18,    15,
};
2024 南京大学《操作系统:设计与实现》
处理器调度:原理

CFS 优先级:“子弹时间”

2024 南京大学《操作系统:设计与实现》