从单节点到多节点-计算性能优化的思考

0.简介

本文用于介绍近期关于性能优化的一些思考,主要在于如何高效进行多节点并行计算的优化,以及单节点如何利用现代的CPU特点和缓存特点高效的去执行计算。

1.多节点优化

多节点计算优化可以考虑两点:一是如何高效协调各节点,可以通过生成合适的分布式执行计划,尽可能让多的节点参与计算,同时采用合理的分布式共识策略,减少这部分造成的延迟和等待;二是尽可能减少数据的重分布,如果不是存算分离架构应尽可能采取合理的分布策略,在计算时尽可能少的重分布(如果是存算分离理论上可以很少的进行数据重分布)。

2.单节点优化

单节点性能优化多核的话可以尽可能利用多核资源,采用多线程来进行操作,线程数可以根据线程类型来进行设置,IO密集型线程数量应多些,计算密集型可稍多于核数即可。简单估算公式如下,根据实际情况调整:
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
接下来分析cpu和缓存特点来对性能优化做分析

2.1 现代CPU运行的理解

超标量流水线和乱序执行:
CPU指令执行可以分为多个阶段(如取址、译码、取数、运算等);

1)超标量:一个cpu核可以多个控制单元,也就是说,可以有多个流水线并发执行;也就是是说如果是没有前置依赖的指令就可以被取出并发的执行。

2)流水线:一个控制单元可以同时执行多个指令,只是每个指令在不同阶段,像一个取址,一个一码,一个取数等。

从上面描述可以看出,程序需要做到以下几个方面,就能提高超标量流水线的每时钟周期的执行指令数:

1)流水线最好是不要断,这就需要尽可能少的程序分支。

2)并发指令越多越好,指令之间尽量去掉依赖就能多个流水线并发执行。

2.2 分支预测

如上所说,程序分支少,流水线效率高,但很多时候程序分支无法避免,如果将分支分类,可以分为有条件(if/switch等)和无条件的跳转(地址跳转(函数调用)/指针跳转(虚函数))。为了执行跳转指令,在得到跳转指令之前,cpu是不知道去哪取下一条指令的,流水线只能等待,为了提高效率,引入了一组寄存器,记录最近几个地址,如果执行时直接在寄存器取出,如果取错了再重新取。可以使用likely或者unlikely来去做分支的预测,处理虚函数跳转可以使用模板编程等方式来减少开销。

2.3 多级存储与数据预取

多级存储,就是在寄存器、cache或内存中,cpu取用速度相差极大,其如果程序访问数据存在线性访问的模式,cpu会主动将后续的内存块预先载入cache,这就是数据预取。如果不是线型的,也可以使用cpu提供的数据预取指令,就是Software Prefetch。

2.4 SIMD

单指令多数据流,对于计算密集型程序来说,可能经常会需要对大量不同的数据进行同样的运算。SIMD引入之前,执行流程为同样的指令重复执行,每次取一条数据进行运算。
例如有8个32位整形数据都需要进行移位运行,则由一条对32位整形数据进行移位的指令重复执行8次完成。
SIMD引入了一组大容量的寄存器,一个寄存器包含832位,可以将这8个数据按次序同时放到一个寄存器。同时,CPU新增了处理这种832位寄存器的指令,可以在一个指令周期内完成8个数据的位移运算。
SIMD资料:https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html

2.5 数据结构优化

数据结构优化其实就是如何让其符合多级存储的结构,如何能利用SIMD。比如将一些合适的数据类型的hash表key和value连续存储,一次性取出;使用字符串池,利用地址来比较是否相等,减少大字符串的来回取用等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习随笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值