找回密码
 立即注册
首页 业界区 安全 现代CPU调优5性能分析方法

现代CPU调优5性能分析方法

泻缥 2025-6-1 19:03:27
5 性能分析方法

当您正在进行高级优化时,例如将更好的算法集成到应用程序中,通常很容易看出性能是否提高,因为基准测试结果通常很明显。从性能分析的角度来看,2 倍、3 倍等大幅提速相对明显。当你从程序中删除大量计算时,你会期望看到运行时间的明显差异。
但同样,在某些情况下,当你看到执行时间的微小变化,比如 5% 时,你却不知道它来自哪里。仅凭计时或吞吐量测量无法解释性能上升或下降的原因。在这种情况下,我们需要深入了解程序是如何执行的。在这种情况下,我们就需要进行性能分析,以了解我们观察到的速度变慢或变快的根本原因。
性能分析类似于侦探工作。要解开性能之谜,就需要收集所有可能的数据并尝试形成假设。一旦有了假设,就需要设计一个实验来证明或推翻它。在找到线索之前,可能会反反复复好几次。就像一个好侦探一样,你要尽可能多地收集证据来证实或反驳你的假设。一旦有了足够的线索,你就可以对观察到的行为做出令人信服的解释。
刚开始处理性能问题时,您可能只有测量数据,例如代码更改前后的数据。根据这些测量结果,你得出的结论是程序变慢了 X%。如果你知道程序变慢发生在某个提交之后,这可能已经为你提供了足够的信息来解决问题。但如果你没有很好的参考点,那么导致速度变慢的可能原因就无穷无尽了,你需要收集更多的数据。收集此类数据最常用的方法之一是对应用程序进行剖析并查看热点。本章将介绍这种方法以及其他几种收集数据的方法,这些方法已被证明在性能工程中非常有用。
下一个问题来了: “有哪些可用的性能数据以及如何收集这些数据?堆栈的硬件层和软件层都有跟踪性能事件并在程序运行时记录这些事件的功能。在这里,硬件指的是执行程序的 CPU,软件指的是操作系统、程序库、应用程序本身以及用于分析的其他工具。通常情况下,软件栈提供时间、上下文切换次数和页面故障等高级指标,而 CPU 则监控缓存未命中、分支预测错误和其他 CPU 相关事件。根据您要解决的问题,有些指标比其他指标更有用。因此,这并不意味着硬件指标总能为我们提供更精确的程序执行概览。它们只是不同而已。有些指标,比如上下文切换次数,CPU 无法提供。性能分析工具(如 Linux perf)可以同时使用操作系统和 CPU 的数据。
性能工程师可能会使用数百种数据源。本章主要介绍硬件级信息的收集。我们将介绍一些最常用的性能分析技术:代码代码插桩、跟踪、特性分析、采样和 Roofline 模型。我们还将讨论静态性能分析技术和编译器优化报告,这些技术无需运行实际应用程序。
5.1 代码插桩 (Code Instrumentation)

可能最早发明的性能分析方法就是代码工具。这是一种在程序中插入额外代码以收集特定运行时信息的技术。下面最简单的示例:在函数开头插入 printf 语句,以指示是否调用了该函数。然后,运行程序并计算输出中出现 “foo 被调用 ”的次数。也许世界上每个程序员在其职业生涯的某个阶段都至少做过一次这样的事情。
  1. int foo(int x) {
  2. + printf("foo is called\n");
  3.   // function body...
  4. }
复制代码
行首的加号表示该行是添加的,在原始代码中并不存在。一般来说,插桩代码并不是要推送到代码库中,而是用于收集所需的数据,之后可以删除。
下例提供了一个更有趣的代码插桩示例。在这个编造的代码示例中,函数 findObject 在地图上搜索具有某些属性 p 的对象的坐标。所有对象最终都会被找到。函数 getNewCoords 返回作为参数提供的较大区域内的新坐标。函数 findObj 返回当前坐标 c 找到正确对象的置信度。如果置信度高于阈值,我们会调用 zoomIn 来找到更精确的对象位置。否则,我们将获取搜索区域内的新坐标,以便下次尝试搜索。
工具代码由两个类组成:直方图和增量器。前者跟踪我们感兴趣的变量值及其出现频率,然后在程序结束后打印直方图。后者只是一个辅助类,用于将数值推送到直方图对象中。在这一假设场景中,我们添加了插桩,以了解在找到对象之前放大的频率。变量 inc.tripCount 计算循环在退出前的迭代次数,变量 inc.zoomCount 计算。
[code]+ struct histogram {+   std::map hist;+   ~histogram() {+     for (auto& tripCount : hist)+       for (auto& zoomCount : tripCount.second)+         std::cout

相关推荐

您需要登录后才可以回帖 登录 | 立即注册