倚天性能优化—ptg-optimize高性能基础库

简介: ptg-optimize为平头哥数据中心解决方案团队开发的一款高性能库,该高性能库借助倚天的硬件架构优势,通过算法设计优化、SIMD向量化、指令优化等,实现包括mem、string、crc32、crypto、spinlock、等20+常用接口的性能优化,mem/string/spinlock等常用接口对标glibc 2.32,crc32/crypto等接口对标业务常用标准化接口。经测试,当前版本优化接口平均性能提升超过50%,性能优化效果显著,集成使用便捷,已为包括集团ebs存储、tair、rds数据库等多种场景提供应用性能加速。

1. 背景介绍

1.1 问题&思考

     由于业务长期在x86架构下进行软件开发,业务侧对x86架构的性能优化有较多经验积累,代码在x86指令集下运行性能良好,当业务由x86切倚天710后,部分热点接口如何与倚天710的硬件能力深度融合、提升热点接口性能来促成业务软件更好的运行在倚天710平台,是当前面临的一个挑战;

     业务对常见热点接口的优化诉求强烈,但是对全量的库升级如(glibc版本升级)保持慎重,我们交流过较多的业务,他们当前的glibc常见接口版本为glibc 2.32,甚至部分还是用glibc 2.17,基于此判断,我们把业务常用的glibc常见接口优化也归划进来,让用户不需要升级glibc版本,就能享受到比最新glibc版本性能更优的接口性能。

1.2 策略

     ptg-optimize为平头哥数据中心解决方案团队开发的一款高性能库,该高性能库借助倚天的硬件架构优势,通过算法设计优化、SIMD向量化、指令优化等,实现包括mem、string、crc32、crypto、spinlock、等20+常用接口的性能优化,mem/string/spinlock等常用接口对标glibc 2.32,crc32/crypto等接口对标业务常用标准化接口。经测试,当前版本优化接口平均性能提升超过50%,性能优化效果显著,集成使用便捷,已为包括集团ebs存储、tair、rds数据库等多种场景提供应用性能加速。

2. 高性能库系统框图



网络异常,图片无法展示
|

     如上为高性能库系统框图,绿色部分为已经实现的接口,红色部分为规划待实现的接口,已实现包括glibc 2.32中常见的mem、string等接口10+个,以及CRC32等业务侧常用的标准化接口4+个,crc32_with_memcpy等业务侧定制化接口2+个(业务热点中对同一串inputString先做copy,随后做crc32,平头哥数据中心解决方案团队通过定制优化,将crc32与copy整合在同一个接口中,来实现性能的大幅提升),crypto加解密SM4、AES相关的接口6+个,锁相关的接口6+个。后续我们将继续补齐glibc 2.32常见接口、hash常见接口的优化。

3. 优化接口列表

     优化接口包括如下,后续我们会持续迭代,新增优化接口,如果业务侧在上倚天710过程中有函数热点需要优化,欢迎联系我们,我们将评估需求并规划进版本迭代中:

#define LIBOPTIMIZE_API attribute((visibility("default")))voidptg_memcpy_neon(voiddst, constvoid*src, size_tn);
voidptg_memcpy_less32(voiddst, constvoid*src, size_tn);
voidptg_memcpy_crc32c(voiddst, constvoidsrc, size_tn, uint32_tcrc);
intptg_spin_lock(pthread_spinlock_t*lock);
intptg_spin_unlock(pthread_spinlock_t*lock);
intptg_spin_lock_cas(pthread_spinlock_t*lock);
intptg_spin_unlock_cas(pthread_spinlock_t*lock);
boolptg_atomic32_compare_exchange_n(volatileuint32_tptr, uint32_texpected, uint32_tdesired);
boolptg_atomic64_compare_exchange_n(volatileuint64_tptr, uint64_texpected, uint64_tdesired);
boolptg_atomic32_ldst_compare_exchange_n(volatileuint32_tptr, uint32_texpected, uint32_tdesired);
boolptg_atomic64_ldst_compare_exchange_n(volatileuint64_tptr, uint64_texpected, uint64_tdesired);
/*Polynomial 0x04C11DB7*/uint32_tptg_crc32(uint32_tcrc, constunsignedchar*data, size_tlen);
uint16_tptg_crc16(uint32_tcrc, constunsignedchar*data, size_tlen);
/*Polynomial 0x1EDC6F41*/uint32_tptg_crc32c(uint32_tcrc, constunsignedchar*data, size_tlen);
uint32_tptg_crc32c_with_memcpy(uint32_tcrc, constunsignedchardata, size_tlen, voiddst);
uint16_tptg_crc16c(uint32_tcrc, constunsignedchar*data, size_tlen);
​intptg_memcmp_len20(constvoids1, constvoids2, size_tn);
intptg_memcmp(constvoids1, constvoids2, size_tn);
voidptg_memchr(constvoidbuf, charch, unsignedcount);
voidptg_memrchr(constvoidbuf, charch, unsignedcount);
voidptg_memset(voids, intc, size_tn);
​charptg_strchr(constchars, intc);
charptg_strchrnul(charstr,intc);
intptg_strcmp(constchars1, constchars2);
​externLIBOPTIMIZE_APIintneon_sm4_ctr_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_sm4_ctr_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_sm4_cbc_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_sm4_cbc_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_aes_xts_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_aes_xts_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_aes_ctr_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
​externLIBOPTIMIZE_APIintneon_aes_ctr_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);

4. 如何优化

倚天710基于armv9指令集架构,有如crc、aes、bf16、sve/neon等特性能力,L1、L2  i/dcache等均相比icelake有较大优势,具体特性如下图所示:



网络异常,图片无法展示
|
网络异常,图片无法展示
|

我们团队通过对倚天710微架构特性的剖析,基于top-down模型视角,在微指令融合、热点指令重排、访存预取、SIMD向量化(sve/neon)、循环展开、pmul+eor+crc32指令流取代crc32单指令来提升后端ALU吞吐等一些列手段,系统性优化接口性能,使常见接口在倚天710上高效运行。



网络异常,图片无法展示
|
网络异常,图片无法展示
|

由于接口较多,我仅选取如下5个接口来说明我们的优化思路及方法,如果读者对其他接口的优化也感兴趣,欢迎钉钉联系我们:

4.1 spinlock接口优化

自旋锁为glibc 2.32中提供了标准接口,该接口为多线程业务提供共享临界区的保护,倚天710单片128core,自旋锁通过对锁的原子操作实现,通过EMSI C2C协议保证数据的有效性,当同一时刻对同一cacheline的monitor监听core数增加时,即同一时刻较多线程在争抢同一个原子变量,会导致系统整体的吞吐性能下降:



为了提升多线程抢锁的性能,我们在自旋锁的内部实现上引入了casal以及随机散列算法,来降低同一时刻线程争抢同一原子操作的次数,极大提升了系统的并发性能,在抢锁位置插入随机打散算法,通过争抢失败的次数来作为随机生成变量来等待N个wfe:

测试多线程抢锁数据如下,结果表明,线程越多、争抢越激烈的场景,性能提升越多,提升2-20倍性能;



4.2 crc32接口优化

crc32为各个业务常用的标准接口,当前标准接口通过集成通用的crc32指令,可以达到较高的性能收益,但是每个core的crc32硬件引擎只有一个,后端backend成为影响整体吞吐的瓶颈点,我们通过引入eor以及pmul指令来计算crc32,提升了后端ALU引擎的并发使用度,达到了较高的性能收益:

相比标准使用crc32指令的接口,提升后端吞吐后的性能平均提升35%+,如下图所示,对crc32重载的业务有相当大的收益,当前已落地ebs存储业务;



4.3 sm4国密接口优化



SM4-CTR算法是一种基于SM4分组加密和CTR模式的对称加密算法,具有高效和安全性等优点,因为算法使用的是块加密的CTR模式,可以将固定长度的明文块转换成密文块,CTR模式具有并行处理能力,因此在实际应用中适合大规模数据的加密解密。其加密流程如下:

1. 初始化:选择一个固定长度的计数器nonce和密钥K,并从初始值开始,按照CTR模式进行初始化。

2. 生成密钥流:使用SM4算法加密计数器nonce,产生M-bit的密钥流Keystream(M为SM4短块长度)。

3. 加密:将Keystream和明文异或,生成密文Ciphertext,并更新计数器nonce的值。

4. 重复执行步骤2和3,直至所有明文块加密完成。

在2,3步骤中,在liboptimize库中我们使用armv8 sm4e进行加速,并通过.inst指令转换为机器码,进一步缩减指令数;

优化前后性能数据对比如下图所示,其中rds数据库集成该优化库算法后,端到端提升了加解密场景性能20%,当前已跟rds数据库完成联调测试;



4.4 memcpy接口优化

memcpy为各个业务常调用的接口,我们借助sve及neon向量化以及部分指令重排、

cacheline预取,相比glibc 2.32中的memcpy,极大提升了在256Bytes以上的性能;

优化后接口相比glibc 2.32平均提升45%,当前已落地到存储ebs业务中,并与tair业务进行联调中:



4.5 ptg_crc32c_with_memcpy接口优化

除了优化标准化接口,我们还会根据业务的实际做定制化优化,如ebs存储业务,他们业务中对crc32的计算负载较大,同时,用来做crc32计算的inputString需要提前做memcpy来获取,基于此场景,我们跟业务方对齐思路,可以在memcpy inputString过程中,就把这串inputString的crc32一并计算出来,可以极大的降低访存延迟:

优化后接口相比客户原先使用crc32+memcpy两次调用方式,可以提升100%的性能,当前已落地至ebs存储业务中:




相关文章
|
存储 缓存 监控
安谋科技(Arm China)马闯:Arm架构下性能分析与优化介绍
2023年9月19日,系列课程第九节《Arm®架构下性能分析与优化介绍》正式上线,由安谋科技 (Arm China)主任工程师马闯主讲,内容涵盖:Arm架构下性能监控单元 (PMU) 介绍、Arm统计性能分析扩展 (SPE) 介绍、Arm性能分析工具介绍、Arm架构下性能优化案例分享,本期节目在阿里云官网、阿里云微信视频号、阿里云钉钉视频号、InfoQ官网、阿里云开发者微信视频号、阿里云创新中心直播平台 & 微信视频号同步播出,同时可以点击【https://developer.aliyun.com/topic/ecs-yitian】进入【倚天实例迁移课程官网】了解更多内容。
|
机器学习/深度学习 人工智能 TensorFlow
倚天产品介绍|倚天性能优化—YCL AI计算库在resnet50上的优化
Yitian710 作为平头哥第一代ARM通用芯片,在AI场景与X86相比,软件生态与推理性能都存在一定的短板,本文旨在通过倚天AI计算库的优化,打造适合ARM架构的软件平台,提升倚天性能
|
Web App开发 存储 缓存
RDMA优化整理(一)
简要的介绍了下RDMA的背景,并给出了一些RDMA编程优化技巧
5390 1
RDMA优化整理(一)
|
4月前
|
JavaScript Linux iOS开发
OpenCode 安装全攻略:4 种方式覆盖 Windows、macOS、Linux
本文深度解析2026年热门开源AI编程代理OpenCode,聚焦“安装难”痛点,详解四大跨平台安装方式(一键脚本、npm、包管理器、桌面包),对比适用场景与坑点,并延伸至模型配置、项目初始化等工程落地关键环节,助力开发者高效启用。
|
10月前
|
数据库
各种锁的专题
数据库锁机制简介:包括写锁(排他)、共享锁(读)、排他锁、间隙锁、行锁、表锁及分布式锁,用于控制并发访问,保证数据一致性与完整性。
|
存储 人工智能 搜索推荐
详解MySQL字符集和Collation
MySQL支持了很多Charset与Collation,并且允许用户在连接、Server、库、表、列、字面量多个层次上进行精细化配置,这有时会让用户眼花缭乱。本文对相关概念、语法、系统变量、影响范围都进行了详细介绍,并且列举了有可能让字符串发生字符集转换的情况,以及来自不同字符集的字符串进行比较等操作时遵循的规则。对于最常用的基于Unicode的字符集,本文介绍了Unicode标准与MySQL中各个字符集的关系,尤其详细介绍了当前版本(8.0.34)默认字符集utf8mb4。
|
人工智能 弹性计算 Cloud Native
平头哥杨平超:倚天CPU架构以及产品特性介绍
2023年8月8日,【倚天实例迁移课程】首节课程《倚天CPU架构以及产品特性介绍》正式上线,由平头哥倚天解决方案架构师杨平超主讲,内容涵盖:倚天710芯片概述;倚天710的主要特点;倚天710应用落地介绍,本期节目也在阿里云官网、阿里云微信视频号、阿里云钉钉视频号、InfoQ官网、阿里云开发者微信视频号、阿里云创新中心直播平台&微信视频号同步播出。
平头哥杨平超:倚天CPU架构以及产品特性介绍
|
测试技术 数据库
『软件测试2』 关于黑盒测试和测试用例的基础知识
该文章讲解了黑盒测试的基本概念以及如何编写有效的测试用例,包括选择合适的输入数据、预期结果的设定和测试执行的步骤。
|
SQL 关系型数据库 MySQL
MySQL并行复制的深入浅出
一、并行复制的背景 首先,为什么会有并行复制这个概念呢?1. DBA都应该知道,MySQL的复制是基于binlog的。 2. MySQL复制包括两部分,IO线程 和 SQL线程。 3. IO线程主要是用于拉取接收Master传递过来的binlog,并将其写入到relay log 4. SQL线程主要负责解析relay log,并应用到slave中 5. 不管怎么说,IO和SQL线程都是单线程的,然后master却是多线程的,所以难免会有延迟,为了解决这个问题,多线程应运而生了。
14192 0
|
开发者 C# UED
WPF与多媒体:解锁音频视频播放新姿势——从界面设计到代码实践,全方位教你如何在WPF应用中集成流畅的多媒体功能
【8月更文挑战第31天】本文以随笔形式介绍了如何在WPF应用中集成音频和视频播放功能。通过使用MediaElement控件,开发者能轻松创建多媒体应用程序。文章详细展示了从创建WPF项目到设计UI及实现媒体控制逻辑的过程,并提供了完整的示例代码。此外,还介绍了如何添加进度条等额外功能以增强用户体验。希望本文能为WPF开发者提供实用的技术指导与灵感。
1047 0