示例2:列访问循环检测优化
简介

针对上述二维数组,在内存中是按行顺序排列的,即X00、X01、X02、X03、……、X10、X11、X12、X13……处理器从内存获取数据时,会获取该数据及其他附近共64字节(Cache Line长度)的数据,例如获取X00,实际也会读取X00后面的X01、X02……这样接下来处理器要读取X01的数据时,它就不需要再访问内存了,而直接从Cache中就能获取到。所以,程序按行顺序读取数据,节省了访存的时间,性能就很高。如果按列读取,读取X00时缓存的数据中可能并不包含X10,所以接下来访问X10时,访问缓存失败,又需要访问内存。
环境准备
Cache_miss数组访问工具检测
- 程序准备。编译cache_miss.c并赋予执行文件所有用户可读、可写和可执行权限。
gcc -g cache_miss.c -o cache_miss && chmod 777 cache_miss
- 采用热点函数分析cache_miss程序,找到热点函数和指令。
单击系统性能分析后面的
,选择“通用分析”,打开新建任务页面,选择“热点函数分析”,参数配置完成后单击“确认”启动热点函数分析任务。图1 新建热点函数分析任务
表1 任务参数配置说明 参数
说明
分析类型
热点函数分析。
分析对象
应用。本示例分析的热点函数为已确定程序,所以不需在服务器上运行程序,直接在工具中选择cache_miss程序。
模式
Launch application。
应用路径
输入程序所在的绝对路径,例如本示例将代码样例放在服务器“/opt/testdemo/cache/cache_miss/cache_miss”目录下。示例路径中的第一个cache_miss为文件夹,第二个cache_miss为可执行程序。
采样时长(s)
30秒。
采集调用栈
开启。
采样范围
用户态。采样范围分用户态、内核态、所有。因为发现所有的CPU消耗都在用户态,所以只采集用户态的数据。
dwarf
开启。
C/C++ 源文件目录
用于采集过程时关联源码。本示例使用/opt/testdemo/cache/cache_miss/。
其他参数
默认。
- 查看采集分析结果。图2 热点函数分析结果总览
在下面的热点函数中,可以看到cache_miss程序中的main函数占用了所有的时钟周期数;单击蓝色函数名,可查看源码对应行数。
优化方案
- 程序准备。
编译cache_hit.c并赋予执行文件所有用户可读、可写、可执行权限。
gcc -g cache_hit.c -o cache_hit && chmod 777 cache_hit
- 采用热点函数分析功能进行分析。单击系统性能分析后面的
,选择“通用分析”,打开新建任务页面,选择“热点函数分析”,参数配置完成后单击“确认”启动热点函数分析任务。
图3 新建热点函数分析任务
表2 任务参数配置说明 参数
说明
分析类型
热点函数分析。
分析对象
应用。
模式
Launch application。
应用路径
输入程序所在的绝对路径,例如本示例将代码样例放在服务器“/opt/testdemo/cache/cache_hit/cache_hit”目录下。示例路径里面第一个cache_hit为文件夹,第二个cache_hit为可执行程序。
采样时长(s)
30秒。
采集调用栈
开启。
采样范围
用户态。采样范围分用户态、内核态、所有。因为发现所有的CPU消耗都在用户态,所以只采集用户态的数据。
dwarf
开启。
C/C++ 源文件目录
用于采集过程时关联源码。本示例使用/opt/testdemo/cache/cache_hit/。
其他参数
默认。
- 查看采集分析结果。图4 热点函数分析结果总览
比较cache_hit和cache_miss程序的热点函数分析结果,优化后的程序运行时间和周期数远远小于未优化前的。
此处数值根据sampling采集数据得来,非绝对值,不同环境的数值可能有较大差别,主要关注优化前后的变化。
结果分析
优化循环体后的cache_hit函数执行时间明显降低。