关于多核 CPU 自旋锁 (spinlock) 的优化

简介: CPU的总线为铜薄膜,虽然摩尔定律使单位面积晶体管的密度不断增加,但是对于连接导线的电阻却没有明显的下降,导线的RC延迟几乎决定现有CPU性能,因此我们会看到传输数据在CPU的角度来看是个极为沉重的负担。我们看到intel 为了引入更多的CPU核心,从Skylake开始芯片总线由上一代的 ring-bus 转变为 2D-mesh, 虽然2D-mesh为数据提供了更多的迁移路径减少了数据堵塞,但也同

CPU的总线为铜薄膜,虽然摩尔定律使单位面积晶体管的密度不断增加,但是对于连接导线的电阻却没有明显的下降,导线的RC延迟几乎决定现有CPU性能,因此我们会看到传输数据在CPU的角度来看是个极为沉重的负担。我们看到intel 为了引入更多的CPU核心,从Skylake开始芯片总线由上一代的 ring-bus 转变为 2D-mesh, 虽然2D-mesh为数据提供了更多的迁移路径减少了数据堵塞,但也同样为数据一致性带来更多问题,例如过去ring-bus 结构下对于存在于某个CPU私用缓存的数据争抢请求只有两个方向(左和右), 但是在2D-mesh环境下会来自于4个方向(上,下,左,右),同时大家不久会看到更多CPU socket的服务器将会出现,为了优化现有的和将来会出现的自旋锁问题,我们开展了自旋锁的优化工作,在代码中具体包含了以下优化方法:

  1. MCS spinlock
    MCS 优化原理( 最新的Linux Kernel也采用了MCS)能够减少锁在不同CPU核心之间的迁移

具体参照:http://www.cise.ufl.edu/tr/DOC/REP-1992-71.pdf

  1. Critical Section Integration (CSI)
    本质上自旋锁产生的效果就是一个CPU core 按顺序逐一执行关键区域的代码,所以在我们的优化代码中将关键区域的代码以函数的形式表现出来,当线程抢锁的时候,如果发现有冲突,那么就将自己的函数挂在锁拥有者的队列上,然后使用MCS进入spinning 状态,而锁拥有者在执行完自己的关键区域之后,会检测是否还有其他锁的请求,如果有那么依次执行并且通知申请者,然后返回。可以看到通过这个方法所有的共享数据更新都是在CPU私用缓存内完成,能够大幅度减少共享数据的迁移,由于减少了迁移时间,那么加快了关键区域运行时间最终也减少了冲突可能性。

具体参照:https://users.ece.cmu.edu/~omutlu/pub/acs_asplos09.pdf

  1. NUMA Aware Spinlock (NAS)
    当前服务器多CPU socket (2/4/8) 给我们提供了更好的性能/功耗比值,但由于CPU片外的数据传输非常昂贵(慢),也引入了更加复杂的一致性需求。 所以我们引入了分布式一致性机制来减少锁的缓存行在不同CPU socket 之间的迁移,最终加速性能。

具体可以参照:https://www.usenix.org/system/files/conference/atc17/atc17-kashyap.pdf

  1. Mutex Schedule per core
    当线程数大于CPU核数的时候, 在自旋锁的场景下由于操作系统的CFS调度,那些没有抢到锁的线程

或者刚刚开始抢锁的线程会不断争抢锁的拥有者和已经处于spinning 状态线程的CPU资源。为了解决
这个问题我们为每一个CPU core 引入mutex, 这样在任何一个阶段只有一个线程可以进入spinning 状
态或者成为锁的拥有者。由于mutex 锁总是存在CPU core 的私用缓存,另外第一个获取mutex锁的线
程数据不会引入任何的系统调用,最终解决了OS带来的问题,数据表明该方法大大提升了整体性能。

  1. Optimization when NUMA is ON or OFF
    虽然NUMA ON可以减少程序访问内存的延迟,但是如果有些程序需要更大的内存带宽,NUMA OFF也是很好的选择。因此在本次优化中我们的代码同时考虑了 NUMA ON 和 NUMA OFF

以下是具体提升数据(与GLIBC pthread_spinlock 对比):
23_34_04__11_26_2018.jpg

使用同样的测试代码,由上图2个CPU socket 变为4个CPU socket(即使是NUMA off), 我们看到了又再次动态的提升了一倍的比例(由96核心的15倍变为192核心的30倍),说明我们的优化持续有效减少了数据和锁的迁移,最终提升性能。
图片.png

最新代码:http://gitlab.alipay-inc.com/eff/numa-spinlock

在进行软件优化的同时,我们看到仍然存在不必要的数据迁移,而这些问题必须有对应CPU硬件指令,为了彻底解决自旋锁问题,我们已经提出了CPU优化方案, 通过该方案可以达到自旋锁的理论值。

虽然性能得到提升,但是我们希望着重说明,如果能够避免使用这个技术,即避免产生由于同步导致的数据传输,才是最佳方案。举例说明:如果一个任务可以并行化并且我们有64个CPU核心, 但他们之间只有1%的串行化代码(如即使性能达到理论值的Spinlock操作), 那么根据 阿姆达尔法则,我们的吞吐量提升度是: T/(0.99T/64 + 0.01T) = 1/(0.99/64 + 0.01) = 39.26, 也就是说64个核心只给了我们40个核心的吞吐量,因此spinlock会严重影响吞吐量。越来越多的经验提醒我们,我们学习技术的目的也许是为了理解事物的规律,从而避免使用这些技术,例如如果使用好的设计从而避免产生同步,不使用spinlock的吞吐量一定是最大的,对么?

目录
相关文章
|
2月前
|
编译器 Linux C语言
C++新特性“CPU优化对齐”
C++新特性“CPU优化对齐”
|
2月前
|
存储 机器学习/深度学习 测试技术
mnn-llm: 大语言模型端侧CPU推理优化
mnn-llm: 大语言模型端侧CPU推理优化
321 1
|
2月前
|
存储 缓存 算法
如何优化 CPU 通道的使用
如何优化 CPU 通道的使用
41 0
|
4月前
|
分布式计算 并行计算 Hadoop
【云计算与大数据计算】分布式处理CPU多核、MPI并行计算、Hadoop、Spark的简介(超详细)
【云计算与大数据计算】分布式处理CPU多核、MPI并行计算、Hadoop、Spark的简介(超详细)
93 0
|
4月前
|
存储 人工智能 缓存
探索AIGC未来:CPU源码优化、多GPU编程与中国算力瓶颈与发展
近年来,AIGC的技术取得了长足的进步,其中最为重要的技术之一是基于源代码的CPU调优,可以有效地提高人工智能模型的训练速度和效率,从而加快了人工智能的应用进程。同时,多GPU编程技术也在不断发展,大大提高人工智能模型的计算能力,更好地满足实际应用的需求。 本文将分析AIGC的最新进展,深入探讨以上话题,以及中国算力产业的瓶颈和趋势。
|
5月前
|
存储 缓存 Linux
高效利用CPU缓存一致性:优化技巧与策略分析
高效利用CPU缓存一致性:优化技巧与策略分析
|
8月前
|
SQL 存储 关系型数据库
记一次MySQL CPU被打满的SQL优化案例分析
记一次MySQL CPU被打满的SQL优化案例分析
170 0
|
10月前
|
NoSQL 安全 Linux
Redis 从入门到精通之内存和CPU配置优化
Redis 是一种基于内存的数据存储系统,因此内存的规划是非常重要的。在配置 Redis 内存时,应该避免物理内存使用过量导致大量使用 Swap,同时需要考虑内存碎片的问题。根据多年的经验整理了一些建议
509 2
|
11月前
|
缓存 iOS开发 芯片
CPU多核增20%符预期,GPU大涨50%达3万分,苹果M2跑分曝光
CPU多核增20%符预期,GPU大涨50%达3万分,苹果M2跑分曝光
164 0
|
SQL 缓存 负载均衡
线上cpu报警的一次接口优化
春天到了大地都复苏了,沉寂了很久的cpu也开始慢慢复苏了,所谓前人埋坑后人填坑,伴随着阿里云监控报警,线上CPU使用率暴增,于是就开始了排查之路。