36

震惊,用了这么多年的 CPU 利用率,其实是错的

 4 years ago
source link: https://www.tuicool.com/articles/F3QvQnR
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

来源: 内核月谈, 原文链接:

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

本文中若有任何疏漏错误,责任在于编译者。有任何建议和意见,请回复 内核月谈 微信公众号,或通过 caspar at linux.alibaba.com 反馈。

导读: 本文翻译自 Brendan Gregg 去年的一博客文章 “CPU Utilization is Wrong”,从标题就能想到这篇文章将会引起争议。 文章一上来就说,我们“人人皆用、处处使用,每个性能监控工具里都在用”的  top  命令里的 “%CPU” 指标,是不对的,其并非用于衡量 CPU 的繁忙程度的正确指标,作者谴责了一下众人(或许也包括你我)的这一行为是具有很大的误导性(deeply misleading)的,而且这种情况还在连年恶化。 对于这么大一顶帽子,让我们暂且按下躁动的心,听听作者是怎么深入阐释他的观点的。

1. 引言

可能你认为的 90% CPU 利用率意味着这样的情形:

而实际却可能是这样的:

CPU 并非 90% 的时间都在忙着,很大一部分时间在等待,或者说“停顿(Stalled)”了。这种情况表示处理器流水线停顿,一般由资源竞争、数据依赖等原因造成。多数情况下表现为等待访存操作,其中又以读操作为主。在停顿周期内,不能执行指令,这意味着你的程序不往前走。值得注意的是,图中 “Stalled” 状态所占的比例是作者依据生产环境中的典型场景计算而来,具有普遍现实意义。因此,大多时候 CPU 处于停顿状态,而你却不知道,因为 CPU 利用率这个指标没有告诉你真相。通过进一步分析 CPU 停顿的原因,可以指导代码优化,提高执行效率,这是我们深入理解CPU微架构的动力之一。

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

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

那么这个所谓“利用率”的问题在哪儿呢?

当今时代,CPU 执行速度远远大于内存访问速度,等待访存的时间成为占用 CPU 时间的主要部分。当你在 top 中看到很高的 “%CPU”,你可能认为处理器是瓶颈,但实际上却是内存。在过去很长一段时间内,CPU 频率增长的速度大于 DRAM 访存延时降低的速度(CPU DRAM gap),直到2005年前后,处理器厂商们才开始放弃“频率路线”,转向多核、超线程技术,再加上多处理器架构,这些都导致访存需求急剧上升。尽管厂商通过增大 cache 容量、优化 cache 策略、提升总线带宽来试图缓解访存瓶颈,但我们的程序仍深受 CPU stall 困扰。

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

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

z6zEjuq.jpg!web

里我们重点关注的核心度量指标是 IPC(instructions per cycle),它表示 平均每个 CPU cycle 执行的指令数量 ,很显然该数值越大性能越好。 上图中 

IPC 为 0.78,看起来还不错,是不是 78% busy 呢?现代处理器一般有多条流水线,运行 perf 的那台机器,IPC 的理论值可达到 4.0。如果我们从 IPC

的角度来看,这台机器只运行到其处理器最高速度的 19.5%(0.78 / 4.0)。幸运的是,在处理器内部,有很多 PMU event,可用来帮助我们分析造成 CPU stall 的原因。用好 PMU 需要我们熟悉处理器微架构,可以参考 Intel SDM。

4. 最 佳实践是什么?

如果 IPC < 1.0, 很可能是 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 :

Inq2yif.jpg!web

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

除了访存导致的 stall 容易让人误解 CPU 利用率外,还有其他一些因素:

7. 更新:CPU 利用率真的错了吗?

这篇文章引起了大量留言:

  • http://www.brendangregg.com/blog/2017-05-09/cpu-utilization-is-wrong.html 的留言栏;

  • https://news.ycombinator.com/item?id=14301739

  • https://www.reddit.com/r/programming/comments/6a6v8g/cpu_utilization_is_wrong/

总结下作者的回答是:这里讨论的并不是 iowait (那是磁盘IO),而且如果你已经确认是访存密集型,是有些处理办法(参考上面)。

那么 CPU 利用率指标是确确实实错误的,还是只是容易误导?如作者前面所说,他认为许多人把高 CPU 利用率理解为瓶颈在 CPU 上,这一行为才是错误的;其实单看 CPU 利用率并不清楚瓶颈在何处,很多时候瓶颈是在外部。这个指标技术上看是否正确?如果 CPU stall 的周期并不能被其他地方使用,它们是不是也就因此是“忙于等待“(听起来有点矛盾)?在有些情况,确实如此,你可以说 CPU 利用率作为操作系统级别的指标技术上看是对的,但是容易产生误导。从另一个角度来说,有超线程的情况下,那些 stalled 的周期是可以被其他线程使用的,这时 “%CPU” 可能会将可用的周期统计为正在使用,这种情况是错误的。这篇文章作者想关注的是解释清楚这个问题,并给出解决方法建议,但没错,CPU 利用率这个指标本身也是存在一些问题的。

当你可能会说利用率作为一个指标已经不对,Andrian Cockcroft之前讨论已经指出过 (http://www.hpts.ws/papers/2007/Cockcroft_HPTS-Useless.pdf )。

8. 结论

CPU 利用率已经开始成为一个容易误导的指标:它包含访存导致的等待周期,这样会影响一些新应用。也许 “%CPU” 应该重命名为 “%CYC”(cycles的缩写)。要清楚知道 “%CPU” 的含义,需要使用其他指标进行辅助,其中就包括每周期指令数(IPC)。IPC < 1.0 多半意味着访存密集型,IPC > 1.0 多半意味着计算密集型。作者之前的文章中涵盖有 IPC 说明,以及用于测量 IPC 的 Performance Monitoring Counters(PMCs)的介绍。

所有的性能监控产品如果展示 “%CPU”,都应该同时展示 PMC 指标用于解释其真实意义,不要误导用户。比如,可以把 “%CPU” 和 “IPC” 一起放,或者说指令执行消耗周期和 stalled 周期。有这些指标之后,开发者和操作者就能够知道该如何更好地对应用和系统进行调优。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK