倚天710规模化应用 - 性能优化 - 软件预取分析与优化实践

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云服务器ECS,u1 2核4GB 1个月
简介: 软件预取技术是编程者结合数据结构和算法知识,将访问内存的指令提前插入到程序,以此获得内存访取的最佳性能。然而,为了获取性能收益,预取数据与load加载数据,比依据指令时延调用减小cachemiss的收益更大。

2000元阿里云代金券免费领取,2核4G云服务器仅664元/3年,新老用户都有优惠,立即抢购>>>


阿里云采购季(云主机223元/3年)活动入口:请点击进入>>>,


阿里云学生服务器(9.5元/月)购买入口:请点击进入>>>,

1 背景

现代应用,如高性能计算(HPC)、大数据、数据库及数据处理等,对内存的时延大小很敏感。传统的解决方案是通过硬件模块检测规则的内存访问模式(循环步长)进行数据预取,也即是硬件预取方法。如此,处理器可将需要的数据提前加载到快速缓存内存中。然而,这些技术对非规则的内存访问模式,如链表形式的数据结构、通过index间接内存访问数组数据并不适用。
软件预取技术是编程者结合数据结构和算法知识,将访问内存的指令提前插入到程序,以此获得内存访取的最佳性能。然而,为了获取性能收益,预取数据与load加载数据,比依据指令时延调用减小cachemiss的收益更大。更为重要的是,过早预取数据,会导致数据cache超出,还未到用时,数据已经被弹出,进而数据再次load加载。若预取数据较晚,除了load自身数据的时延,还会增加冗余预取数据的时延。所以预取的时机不对常常导致软预取性能提升不明显,甚至性能下降。
结合业界提供了[论文]一种针对间接内存访问模式的自动化插入预取指令的优化算法,不仅可以处理更复杂的间接内存访问模式,而且可以规避提前加载导致的运行错误。核心是采用深度优化查找算法,找到load指令引用的循环归纳变量的路径指令集,进而对路径指令集进行数据提前加载,达到访存数据提前加载的目的。并在科学计算、HPC、大数据、数据库等商业应用,此方法在Intel Haswell架构上平均1.3X提升, Arm Cortex-A57架构有1.1X提升。发现软件预取的性能收益,和look-ahead预测距离、内存宽度、动态指令数及TLB大小强相关。
直观上理解,数据预取的方法,可以通过以下方法实现:

for (int i = 0; i < ARRAYLEN; i++) {
   
    arrayC[i] = arrayA[i] * arrayB[i];
}

增加Prefetch指令的代码,如下所示:

Prefetch(&arrayA[0]);
Prefetch(&arrayB[0]);
for (int i = 0; i < ARRAYLEN - ARRAYLEN % 4; i+=4) {
   
    Prefetch(&arrayA[i + 4]);
    Prefetch(&arrayB[i + 4]);
    arrayC[i] = arrayA[i] * arrayB[i];
    arrayC[i + 1] = arrayA[i + 1] * arrayB[i + 1];
    arrayC[i + 2] = arrayA[i + 2] * arrayB[i + 2]; 
    arrayC[i + 3] = arrayA[i + 3] * arrayB[i + 3];
}

软件预取的方法实现原理基本上述方法类似。
假如数组之间存在间接调用的场景,如

1 for (i=0; i<base_array_size; i++) {
   
2 target_array[func(base_array[i])]++;
3 }

这里,顺序访问的内存数组base_array, 且定义func(x)=x,也即是base_array的结果作为target_array的访问index,故涉及到两种内存访问模式,base_array[i]和target_array[index].这两种械均适用于软预取。但访问target_array地址依赖于base_array结果。硬件预取却不无法精确识别并预取数据。通过软预取技术,可插入预取指令如下:

1 for (int i=0; i<NUM_KEYS; i++) {
   
2 // The intuitive case, but also
3 // required for optimal performance.
4 SWPF(key_buff1[key_buff2[i + offset]]);
5 // Required for optimal performance.
6 SWPF(key_buff2[i + offset*2]);
7 key_buff1[key_buff2[i]]++;
8 }

更重要的是,以合适的预测距离(当前迭代的偏移)插入正确的预取代码,对最终用户来说,是一个挑战。通过上述代码,在第4行插入prefetch指令,性能提升1.08X。然而,在key_buff2和间接数据kye_buffer1均插入prefetch指令,也即是在第6行也插入prefetch,性能提升1.30X。所以,选择合适的预测距离至关重要,可以避免过早或过晚预取数据问题。

2 软件预取

基于LLVM IR,开发软预取优化PASS,思路是通过查找load指令,判别是否可以在数组内预测预取,然后生成软件预取指令。首先生成分析信息,然后代码生成。算法1:
image.png

软预取流程图

3 Benchmark验证

目前,Prefetch优化算法作为LLVM的新增Pass,注册到LLVM-内部的PASS流程中,通过编译选项控制此优化的开关,具有通用性及普适性。
Noahbenchmark是基于服务器提取的权威性验证Benchmark,通过此benchmark可获取比较有说服力的数据。首先验证了noahbenchmark内prefetch内11个场景。通过前后优化对比,每个benchmark场景均有提升,最高达10%+。

基于Prefetch优化,验证SPEC2017性能,总体软预取带来5个benchmark提升,最大提升2.49%,3个benchmark持平,2个benchmark略有下降。

相关文章
|
5月前
|
弹性计算 运维 监控
带你读《云上自动化运维宝典》——提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具(2)
带你读《云上自动化运维宝典》——提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具(2)
|
5月前
|
消息中间件 弹性计算 运维
带你读《云上自动化运维宝典》——提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具(1)
带你读《云上自动化运维宝典》——提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具(1)
|
3月前
|
弹性计算 运维 安全
提升云上资源稳定性的两大利器,事件驱动体系构建&自诊断工具
阿里云弹性计算团队十三位产品专家和技术专家共同分享云上运维深度实践,详细阐述如何利用CloudOps工具实现运维提效、弹性降本。
|
5月前
|
存储 缓存 监控
如何在云原生可观测工具中获得更好的性能
如何在云原生可观测工具中获得更好的性能
|
5月前
|
搜索推荐 数据挖掘 Android开发
数据驱动性能体验优化
数据驱动性能体验优化
|
5月前
|
弹性计算 运维 监控
提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具
阿里云弹性计算技术专家王子龙和阿里云弹性计算技术专家樊超在本次课程中带来了题为《提升云上资源稳定性的两大利器:事件驱动体系构建&自诊断工具》的主题分享, 课程涵盖基于事件构建可观测体系、基于事件的云上运维、ECS事件驱动最佳实践、使用ECS遇到故障时的痛点分析、一眼排障ECS健康状态、一键定位ECS健康诊断等内容。
|
6月前
|
存储 消息中间件 数据库
Milvus性能优化提速之道:揭秘优化技巧,避开十大误区,确保数据一致性无忧,轻松实现高性能
Milvus性能优化提速之道:揭秘优化技巧,避开十大误区,确保数据一致性无忧,轻松实现高性能
Milvus性能优化提速之道:揭秘优化技巧,避开十大误区,确保数据一致性无忧,轻松实现高性能
|
9月前
|
数据采集 算法 编译器
倚天710规模化应用 - 性能优化 -自动反馈优化分析与实践
编译器优化分成静态优化与动态优化,静态优化指传统编译器gcc/llvm时,增加的优化等级,如O1,O2,O3,Ofast,此时,编译器会依据编译优化等级增加一些优化算法,如函数inline、循环展开以及分支静态预测等等。一般情况下,优化等级越高,编译器做的优化越多,性能会更会好。在阿里生产环境中,单纯依赖于静态优化,并不能达到程序运行流畅目的,通过分析CPU硬件取指令、执行指令,往往会出现一些分支预测失败导致iCacheMiss率高的场景,限制了程序的性能进一步提升。基于此,业务引入了动态反馈优化工具,依据生产环境的实际运行数据,反哺指导编译器对程序代码进一步调整编译优化策略,提高分支预准确率
|
11月前
带你读《阿里云卓越架构白皮书》——4、性能优化(1)
带你读《阿里云卓越架构白皮书》——4、性能优化(1)
174 0
|
11月前
带你读《阿里云卓越架构白皮书_导读版》——4、性能优化(2)
带你读《阿里云卓越架构白皮书_导读版》——4、性能优化(2)
178 0
http://www.vxiaotou.com