关于多核 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核心之间的迁移

  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的吞吐量一定是最大的,对么?

目录
相关文章
|
6月前
|
编译器 Linux C语言
C++新特性“CPU优化对齐”
C++新特性“CPU优化对齐”
126 3
|
3月前
|
SQL 监控 关系型数据库
MySQL优化: CPU高 处理脚本 pt-kill脚本
MySQL优化: CPU高 处理脚本 pt-kill脚本
|
1月前
|
存储 缓存 算法
CPU优化
【10月更文挑战第7天】
31 1
|
3月前
|
监控 Java Linux
CPU被打满/CPU 100%:高效诊断与优化策略
【8月更文挑战第28天】在日常的工作与学习中,遇到CPU使用率飙升至100%的情况时,往往意味着系统性能受到严重影响,甚至可能导致程序响应缓慢或系统崩溃。本文将围绕这一主题,分享一系列高效诊断与优化CPU使用的技术干货,帮助大家快速定位问题并恢复系统性能。
223 1
|
4月前
|
NoSQL Redis 开发工具
Redis性能优化问题之检查 Redis 实例是否启用了透明大页机制,如何解决
Redis性能优化问题之检查 Redis 实例是否启用了透明大页机制,如何解决
|
4月前
|
Java
手把手教你java CPU飙升300%如何优化
手把手教你java CPU飙升300%如何优化
61 0
|
4月前
|
监控 Java 中间件
FGC频繁导致CPU 飙升定位及JVM配置优化总结
FGC频繁导致CPU 飙升定位及JVM配置优化总结
165 0
|
4月前
|
缓存 弹性计算 监控
云服务器 CPU 使用率高的问题排查与优化
云服务器 CPU 使用率高的问题排查与优化
417 0
|
5月前
|
SQL 数据处理 API
实时计算 Flink版产品使用问题之holo的io以及cpu使用较为稳定,sink端busy一直在20%左右,有时候50%,该如何优化
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
存储 机器学习/深度学习 测试技术
mnn-llm: 大语言模型端侧CPU推理优化
mnn-llm: 大语言模型端侧CPU推理优化
983 1