🐧 第四章 进程调度器
📄 一句话概括

从实测加速比能反推串行比例:四次测量(4/8/16/32 核)推出的数落在同一个附近,说明模型可靠。工程上这是最有用的一句话——加机器之前先算一笔。

📝 本节和前面几节的关系

4.14 与 4.15 给了两组数据,这一节把它们变成可用的判断法:从加速比反推瓶颈,再决定要不要加机器。

一、阿姆达尔定律怎么反着用

正着用:知道串行比例,算出理论加速比。 反着用:量到加速比,反推串行比例——公式是 串行比例 =(1/加速比 − 1/核数)/(1 − 1/核数)。 实测四次(4/8/16/32 核)反推出来的串行比例落在同一个数附近——这说明模型是对的,也说明那个【串行部分】是真实存在的。 这一步的价值:你不用改代码就能知道【再买机器能快多少】。

二、三种【加核也没用】的情形

一、活儿拆不开。一个进程只能一个核。改算法、拆成可并行的块。 二、卡在共享资源。锁、同一块内存、同一个数据库连接。减少共享、分片、批量。 三、卡在 IO。CPU 在等磁盘或网络。加缓存、换更快的存储。 判据很简单:先看 top 里 CPU 占用率。占用率上不去,加核没用;占用率满了才是真缺 CPU。

三、这笔账怎么算才不亏

加核的成本是线性的(钱),收益是对数的(阿姆达尔)。所以加到某个点之后,每一分钱换来的加速越来越小。 工程上的做法:先算【要提升多少】,再算【需要多少核】,如果那个核数离谱,就说明该改架构。 这条判断能省下很多钱:与其买 64 核,不如把串行部分从 20% 降到 5%——后者往往只要改一段代码。

四、这一章到此为止的两句话

第一句:调度解决【怎么分】,不解决【有多少】。产能由硬件与并行度决定。 第二句:所有性能优化都要说清【代价落在谁身上】。加核的代价是钱,拆任务的代价是复杂度,调 nice 的代价是别人变慢。 这两句合起来,就是判断任何性能方案的标准。

五、动手 Demo:思考——从加速比反推瓶颈

拿四组【核数 + 实测加速比】反推串行比例,看四次推出来的数是不是一致。一致就说明模型可用。

pairs = [(4, 2.5), (8, 3.2), (16, 3.6), (32, 3.8)]
for n, s in pairs:
    # 由 s 反解串行比例:(1-p) = (1/s - 1/n) / (1 - 1/n)
    serial = (1.0 / s - 1.0 / n) / (1.0 - 1.0 / n)
    print(n, "核 实测", s, "倍 -> 串行比例", round(serial, 3))

实跑输出:

--------------------------------------------------------------------
思考——从加速比反推瓶颈
--------------------------------------------------------------------
① 反过来用阿姆达尔:从实测加速比推串行比例

      公式:加速比 = 1 / ((1-p) + p/n),反解得串行比例 1-p

  核数     实测加速     反推的串行比例
  -------------------------------------
  4        2.5 倍       20%
  8        3.2 倍       21%
  16       3.6 倍       23%
  32       3.8 倍       24%

  **四次测量推出的串行比例都落在同一个数附近**——**这说明模型是对的。**
  **工程上这是最有用的一句话**:加机器之前先算一笔,
  **如果串行占两成,那最多只能快五倍,加到多少核都一样。**

② 三种【加核也没用】的情形

  情形             为什么没用               该改什么
  -----------------------------------------------------------------
  活儿拆不开       一个进程只能跑一个核     改算法,拆成可并行的块
  卡在共享资源     锁、同一块内存           减少共享、分片
  卡在 IO          CPU 在等磁盘或网络       加缓存、换更快的存储

  **判据很简单**:先看 `top` 里 CPU 占用率。
  **占用率上不去,加核没用;占用率满了才是真缺 CPU。**

四次反推出来的串行比例都在两成上下——这说明那些核里有一部分时间确实用不上。 工程含义很直接:串行占两成,加速比上限就是 5 倍,加到多少核都一样。 所以【先算再买】比【先买再试】省得多。 如果算出来上限只有 5 倍,而你需要 10 倍——那就别加机器了,去改那段串行的代码。

30 秒实验

  1. 把你的程序在 taskset -c 0 与不限核两种情况下各跑一次,算出加速比,再反推它的串行比例。
  2. perf stat -e task-clock ./程序——看它到底用了多少 CPU 时间。
  3. cat /proc/loadavg 看系统平均负载,与核数比较(超过核数说明在排队)。

常见误区

  1. 【买更快的机器总能解决问题】。如果瓶颈是串行部分或 IO,更快的机器也只是把串行部分变得稍微快一点。
  2. 【加速比算出来是 3 倍,说明还差 5 倍可以挖】。要看上限。上限 5 倍时,你已经做到 3 倍,剩下的空间不多。
  3. 【阿姆达尔定律过时了】。它只是【并行上限】的算术,跟硬件年代无关。
自测三问(点开对答案) 1. 怎么从实测加速比反推串行比例?这个数有什么用? —— 串行比例 =(1/加速比 − 1/核数)/(1 − 1/核数)。**它告诉你【再加核最多还能快多少】**,不用改代码就能算。 2. 三种【加核没用】的情形? —— 活儿拆不开、卡在共享资源、卡在 IO。**判据:先看 CPU 占用率。** 3. 为什么说【加核的成本是线性的、收益是对数的】? —— 钱按核数线性增加,**加速比按阿姆达尔趋近上限**。到某个点之后每一分钱换来的加速越来越小。

相关笔记