每天写1000字

CPU 利用率背后的真相,你知道吗?

2018-12-29  本文已影响132人  皮皮卡卡丘

1、引言

 当CPU利用率90%时,你以为情形是这样滴:


image

 而实际却可能是这样滴:


image
 这说明CPU并不是90%的时间都在有效的工作,其中有很大一部分时间是在等待(Stalled),这个Stalled类型等待与Idle类型等待是不一样的。Idle类型的等待也称为空闲等待,是CPU真实的空闲时间。而Stalled类型等待却常常是由于CPU指令流水中断导致,造成这种中断的原因一般是资源竞争或者数据依赖。多数情况下是在等待程序的访存操作,而这其中又以读操作为主。
 在Stalled等待期间,无法继续执行指令,这意味着当前程序无法继续进行。图中 “Stalled” 状态所占的比例是依据生产环境中的典型场景计算而来,具有普遍的现实意义。

 然而,大多数CPU 处于Stalled类型等待状态时,你无法知晓,这是因为 CPU 利用率这个指标没有告诉你这一点。然而这一点对于指导代码优化,提高运行效率至关重要,值得分析研究。

2、CPU 利用率的真实含义是什么?

 通常意义的CPU利用率指的是 “non-idle time”:即CPU不执行 idle thread 的时间在统计时段中的占比。
 假设一个 non-idle thread 开始运行,100ms 后结束,内核会认为在这段时间内 CPU 利用率为 100%,这种度量方式起源于分时复用系统。早在阿波罗登月舱的导航计算机中,idle thread 就已经存在,当时被叫做 “DUMMY JOB”。工程师通过比对运行 “DUMMY JOB” 和 “实际任务” 的时间比例来衡量导航系统的利用率。

 那么这个所谓的“利用率”到底有什么问题呢?

 当今时代,CPU 执行速度远远大于内存访问速度,等待访存的时间成为占用 CPU 时间的主要部分。当你在 top 中看到很高的 “%CPU”,你可能认为处理器是瓶颈,而实际的瓶颈却可能是内存。
 在过去很长的一段时间内,CPU频率的增长速度都要大于DRAM延迟的降低速度,这也就是常说的内存墙问题(CPU DRAM gap)。2005年前后,处理器厂商开始采用多核和超线程技术,在加上多处理器架构的使用,导致访存需求的急剧上升,进一步加剧了内存墙问题。尽管Cache策略的采用在一定程度上缓解了这种瓶颈,但仍然有很多程序深受CPU Stall的困扰。

3、 如何真正辨别 CPU 在做些什么?

 在 PMC(Performance Monitoring Counters) 的帮助下,我们能看到更多的 CPU 运行状态信息。下图是perf 采集了10秒内全部 CPU 的运行状态。

# perf stat -a -- sleep 10

 Performance counter stats for 'system wide':

     641398.723351      task-clock (msec)         #   64.116 CPUs utilized            (100.00%)
           379,651      context-switches          #    0.592 K/sec                    (100.00%)
            51,546      cpu-migrations            #    0.080 K/sec                    (100.00%)
        13,423,039      page-faults               #    0.021 M/sec                  
 1,433,972,173,374      cycles                    #    2.236 GHz                      (75.02%)
   <not supported>      stalled-cycles-frontend  
   <not supported>      stalled-cycles-backend   
 1,118,336,816,068      instructions              #    0.78  insns per cycle          (75.01%)
   249,644,142,804      branches                  #  389.218 M/sec                    (75.01%)
     7,791,449,769      branch-misses             #    3.12% of all branches          (75.01%)

      10.003794539 seconds time elapsed

 这里重点关注的核心度量指标是 IPC(instructions per cycle),它表示平均每个 CPU cycle 执行的指令数量,很显然该数值越大表示性能越好。上图中IPC 为 0.78,看起来还不错,但是不是意味着CPU有78%的时间处于忙碌状态呢?现代处理器一般有多条流水线,运行 perf 的那台机器,IPC 的理论值可达到 4.0。
如果从 IPC的角度来看,这台机器只运行到其处理器最高速度的 19.5%(0.78 / 4.0)。幸运的是,在处理器内部,有很多 PMU event,可用来帮助分析造成 CPU stall的原因。PMU的使用需要熟悉处理器微架构,可以参考 Intel SDM。

4、最佳实践是什么?

 如果 IPC < 1.0, 此时CPU的利用率高,很可能是由于Memory stall占主导的原因导致,此时可从软件和硬件两个方面来解决这个问题。软件方面:减少不必要的访存操作,提升 cache 命中率,尽量访问本地节点内存;硬件方面:增加 cache 容量,加快访存速度,提升总线带宽。
 如果IPC > 1.0, 很可能是计算密集型的程序。可以试图减少执行指令的数量:消除不必要的工作。火焰图CPU flame graphs,非常适用于分析这类问题。硬件方面:尝试超频,或使用更多的 core 或 hyperthread。作者根据PMU相关的工作经验,设定了1.0这个阈值,用于区分访存密集型(memory-bound)和计算密集型(cpu-bound)程序。读者可以根据自己的实际工作平台,合理调整这个阈值。

5、性能工具应该告诉我们什么?

 作者认为,性能工具中使用 %CPU 时都应该附带上 IPC,或者将 %CPU 拆分为指令执行消耗 cycle(%INS) 和 stalled 的 cycle(%STL)。对应到 top,在 Linux 系统有一个能够显示每个处理器 IPC 的工具 tiptop:

tiptop -                  [root]
Tasks:  96 total,   3 displayed                               screen  0: default

  PID [ %CPU] %SYS    P   Mcycle   Minstr   IPC  %MISS  %BMIS  %BUS COMMAND
 3897   35.3  28.5    4   274.06   178.23  0.65   0.06   0.00   0.0 java
 1319+   5.5   2.6    6    87.32   125.55  1.44   0.34   0.26   0.0 nm-applet
  900    0.9   0.0    6    25.91    55.55  2.14   0.12   0.21   0.0 dbus-daemo

6、其他可能让 CPU 利用率引起误解的因素

除了访存导致的 stall 容易让人误解 CPU 利用率外,还有其他一些因素:
 (1)温度原因导致处理器 stall;
 (2)Turboboost 干扰时钟速率;
 (3)内核使得时钟速率加快;
 (4)统计平均带来的问题:1分钟利用率平均 80%,掩盖了中间 100% 部分;
 (5)自旋锁: CPU 一直在被使用,同时 IPC 也很高,但是应用逻辑上并没有任何进展。

http://www.brendangregg.com/blog/2017-05-09/cpu-utilization-is-wrong.html

上一篇下一篇

猜你喜欢

热点阅读