我们可能经常会遇到程序中热点函数被多个调用者调用的情况,这样就需要知道哪个函数调用foo的次数最多,应用程序的库函数出现在热点处。要理解为什么特定函数会呈现为热点,我们需要知道程序的控制流图中的哪条路径是最热的。
Intel VTune profiler对基准测试x264的源代码和汇编代码分析视图。
分析foo的所有调用者的逻辑可能非常耗时,我们希望只关注那些导致foo为热点的调用者,我们想知道程序的CFG中最热的路径。剖析工具通过在收集性能样本时捕获进程的调用栈以及其他信息来实现这一点。然后,将所有收集的栈进行分分组,从而使我们能够看到导致某个特定函数的最热路径。
用linux perf工具收集调用栈有三种可能的方法。
帧指针 perf record--call-graph fp 需要在二进制构建的时候带上--fnoomit-frame-pointer 参数。
DWARF 调试信息,perf record--call-graph dwarf 需要二进制文件在编译构建时带上DWARF调试信息 -g
intel最后分支记录Last Branch Record 硬件特性,调用图的深度不如前面两种方法,关于LBR的更多信息参见6.2节。
下面是使用Linux perf采集程序调用栈的示例,根据输出结果,我们知道foo有55%的执行时间是从funcl调用的,我们可以清楚的看到foo调用之间的开销分布。
使用Intel vtune profier的时候,可以配置分析功能时选中 收集栈来采集调用栈数据
5.4.4 火焰图
是一种常用的可视化剖析数据和程序最热代码路径的方法,可以让我们看到哪些函数占用了大部分的执行时间。
5.5 屋顶线性能模型
屋顶线性能模型是加利福利亚分校2009提出来的。一种面向吞吐的性能模型,常用语高性能计算,此模型中的屋顶线,表示应用程序的性能不可能超过计算机处理能力的事实,程序中的每个函数和循环都受计算机的计算能力或者内存容量的限制,应用程序受到某个屋顶线函数的限制。
硬件有两个主要限制:计算速度和数据搬移速度。应用程序的最大性能受峰值计算性能和平台带宽算数强度乘积之间的最小值的限制。图24中显示的屋顶线图基于硬件限制绘制了两个应用程序A和B的性能。程序的不同部分可能具有不同的性能特征,屋顶线模型考虑了这一点,可以在同一个图上表示显示应用程序的多个函数和循环。
算术强度是FLOPS 和字节之间的比率,可以根据程序中的每个循环进行计算。现在我们计算代码清淡8中的代码的算术强度,在最内层的循环体中,有一个加法运算和一个乘法运算,因此2个浮点运算,还有三个读操作和一个写操作。
提高应用程序性能的传统方法充分利用计算机的SIMD和多核功能, 通常需要在很方面进行优化,包括向量化,内存,线程。屋顶线方法有助于评估应用程序的这些特征。在屋顶线图上,我们可以绘制标量单核,SIMD单核和SIMD多核性能的理论最大值。可以让我们了解应用程序性能的提高空间。如果发现应用程序是计算密集型的,并且性能低于峰值标量单核性能,则应该考虑强制向量化并利用多个线程分配工作。相反,如果应用程序的算术强度比较低,则应该寻找改善内存访问的方法,使用屋顶线模型性能的最终目标是将点向上移动,向量化和现成话将点向上移动,而通过增加算术强度优化内存访问将点向右移动同事还可能提高性能。
理论最大值,可以根据所使用的计算机的特征计算,计算机理论最大值并不困难。对于Intel Core i5-8259U处理器,具有avx2和2个融合乘加单元的最大FLOPS可以通过如下公式
峰值 FLOPS = 8(逻辑核数量) x 256(avx)位宽/ 32位(浮点数大小)
总之 ,屋顶线性能模型有助于
1 识别性能瓶颈
2 指导软件优化
3 确定何时优化已经达到了极限
4 评估与机器能力相关的性能