0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Ampere Altra系列处理器的锁和内存序

安晟培半导体 来源:安晟培半导体 2023-06-07 17:36 次阅读

AMPERE ALTRA和AMPERE ALTRA MAX 的锁机制

让我们先来了解一些基本的问题。Arm 在 Arm v8.2-A 架构中引入了大型系统扩展(Large System Extensions, LSE),它用单个原子指令取代了锁操作的指令序列。这里 (https://dev.to/aws-builders/large-system-extensions-for-aws-graviton-processors-3eci)是一个非常不错的总结。虽然旧的 Arm 版本在功能上可以很好地工作,但随着核心数量的增加和锁的争用更加频繁,预计性能会受到影响。Ampere Altra 和 Ampere Altra Max 支持 LSE,并配备了可扩展的锁性能。

为了说明使用的指令之间的差异,让我们看看 gcc 的处理方式

__atomic_fetch_add()。在本例中,将锁值减 1:

__atomic_fetch_add(&lockptr->lockval, -1, __ATOMIC_ACQ_REL);

使用* -march =armv8.2-a*选项编译,编译器生成带有原子指令的代码:

998:  f8f60280    ldaddal x22, x0, [x20]

另一方面,设置* -march =armv8-a*(不支持LSE),生成一个不同的序列:

9a4:  c85ffe60  ldaxr  x0, [x19] 
9a8:  d1000400  sub   x0, x0, #0x1 
9ac:  c801fe60  stlxr  w1, x0, [x19] 
9b0:  35ffffa1  cbnz  w1, 9a4 

为了使序列具有原子性,需要一个单独的监视器。ldaxr 获得一个地址标记,在本例中为 [x19]。然后执行减法,然后存储回内存位置。但是,只有当存储(store)时的标记与加载(Load)中的标记匹配时,存储才会成功。stlxr 之后的条件分支 cbnz 检查存储是否成功,这意味着 load 和 store 中的标记匹配。如果不是,则跳回序列的开头,在本例中是地址 0x9a4。

这里值得注意的是,如果没有 LSE 指令,这个指令序列可能要执行几次才能被认为成功。使用 LSE, ldaddal 指令可以保证以一条指令完成,不需要循环。

图 1 显示了当线程数从 1 增加到 80 时,使用 LSE 和不使用 LSE 时每秒获得排他锁的性能差异。

e186c626-0515-11ee-90ce-dac502259ad0.png

图 1

通常,Compare 和 Exchange 硬件指令用于在软件中实现锁。需要注意的是,这些指令必须是原子指令。

原子在这里是什么意思呢?这些指令首先获得包含锁的缓存行(Cache Line)的所有权,并将其加载到 CPU 的本地缓存中。然后将当前值与随指令提交的比较值进行比较。如果相等,作为指令一部分提交的新值将替换当前值。如果不相等,则保持当前值。这方面的原子性意味着整个序列由一个线程执行,而没有其他线程访问缓存行,由硬件保证。

锁的种类

在软件中可以实现不同类型的锁,如互斥锁(mutexes)、票据锁(ticket)和自旋锁(spinlocks)。如前所述,不同的锁类型在软件中实现,硬件提供类似 cmpxchg 或 fetchadd 的指令。相同的锁类型在不同的硬件上运行,只有使用的指令不同。

如何实现锁机制

这是一个非常重要的问题。让我们把它分解成两个选项:1) 使用可用的库和 2) 使用原子指令来实现专有的锁定算法

选项1有几个优点。库已经存在,不需要自定义实现,而且经过了充分测试,通常将会在未来的库版本中进行维护。例如pthread_mutex_lock和pthread_rwlock。听起来不错,那么有什么缺点呢? 缺乏统计数据可能是一个问题。没有向应用程序返回任何信息,报告旋转(spins)或线程被调度出多少次。此外,库实现可能不太适合某些应用程序,因为库更通用。

e1a4144c-0515-11ee-90ce-dac502259ad0.png

pthread_mutex_lock

https://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread_mutex_lock.html

选项 2 更复杂。它需要实现锁定函数并维护它们。但是,它可以获得一些好处,因为它是专门为应用程序设计的。锁定原语和原子指令可以通过内联汇编(inline assembly)或利用编译器的支持来实现。同样,使用内联程序集编写代码需要应用程序维护该段代码。

对于编译器,gcc提供了atomic built-in function,它允许应用程序使用低级函数,这些函数将被编译成 Arm 原子指令。这些内置函数为应用程序提供了原子指令和内存序指令的不同方法。代码也更易于移植。但是,使用*-mcpu或-march*的正确设置来编译应用程序来生成 Arm LSE 指令是很重要的。Ampere Altra 和 Ampere Altra Max 使用 Neoverse-n1 架构,其中就包括LSE。

e1a4144c-0515-11ee-90ce-dac502259ad0.png

atomic built-in function

https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html

然而,使用原子指令实现锁需要设计决策。如果锁被持有,旋转(spinning)是否合理?转几圈?线程在旋转一定次数后如果不成功,是否应该放弃?在旋转环中需要后退,还是直线旋转? 这些只是需要解决的问题中的一部分。

其他的设计决策

1锁的数据类型和大小

通常,应用程序使用 int 或long 作为锁。用于原子操作的内置函数(Built-in functions)从内存中读取锁值。如果应用程序也直接读取锁值,锁类型应该有“volatile”前缀,例如 volatile long。使用 volatile,编译器生成从内存中读取数据的指令。否则,该值可能在寄存器中而没有更新,从而错过对锁位置的更新。

2锁的粒度

由于竞争,粗粒度锁有可能成为性能瓶颈。另一方面,如果每个资源都有自己的锁来保护,那么将需要大量内存来存储锁。必须是一种折衷设计,以避免任何不利因素。

3锁对齐

编译器对结构进行正确对齐。如果应用程序管理自己的内存,那么锁的位置可能与锁的大小不一致。在最坏的情况下,锁可能跨越两条缓存行。在 AArch64 上,对未对齐锁的原子操作会导致 SIGBUS (硬件向操作系统发出信号,表明 CPU 不能寻址内存地址的总线错误,在这种情况下是由于未对齐访问)。从积极的方面来看,获得 SIGBUS 需要固定对齐,而不是隐藏很少被发现的性能问题。

4假共享

虚假分享是什么意思?即同一高速缓存行上的独立数据对性能有不良影响,锁数组就属于这一类。这些锁保护不同的关键区域。但是,对同一缓存行上锁的原子操作会影响该缓存行上的所有锁。重要的是,原子性不是针对锁本身,而是针对包含锁的整个缓存行。

5在 cmpxchg 之前做测试

在执行 cmpxchg 指令之前读取自旋循环(spinloop)中的锁值可能对争用锁有利。Cmpxchg 需要缓存行的所有权,而test将以共享模式获取缓存行,从而避免失效。然而,这可能会增加执行的 spin 数量。

6如果可能的话,在无锁时

使用fetchadd 而不是 cmpxchg

释放锁需要返回线程为获取锁而执行的操作。Cmpxchg,特别是对于共享锁或读写锁,需要一个循环,并且由于锁值的变化而可能会重试操作。然而,fetchadd 不需要循环,没有比较,因此它会成功。

7锁定持有时间

通常指临界区域内的指令数或在临界区域内花费的时间。时间是一个更好的度量标准,因为临界区域可能只有很少的指令。然而,所有的指令都可以从内存中读取。嵌套锁属于同一类别。无法获得内部锁以及 spinning 或 sleeping 会影响外部锁的保持时间。减少关键区域的保持时间总是好的,如果数据在本地缓存而不是内存中就更好了。

8抢占

不幸的是,线程在持有锁时可能会被重新调度。如果锁处于独占模式,这意味着没有其他线程能够获得锁。在考虑性能问题时,要记住这一点。较短的保持时间将降低抢占的可能性。

内存序

如前所述,正确的内存排序指令对于正确性很重要。AArch64 遵循一种宽松的内存模型。使用 LSE, AArch64 指令强制执行特定的内存顺序。例如,cmpxchg 指令集有获取(CASA 指令)、释放(CASL 指令)以及获取和释放(CASAL 指令)的版本。硬件保证这些指令遵循其特定指令的内存模型。这取决于软件使用适当的指令。通常,acquire 用于锁获取,Release 用于锁释放。但是,如果应用程序在无锁之后读取数据(例如,如果该锁有任何等待程序),那么空闲程序的 release 语义可能会导致问题,因为对等待程序结构的读取可能会提升到空闲程序之上,因此在空闲程序之后,寄存器中就会出现陈旧的数据。在这些情况下,最好使用 acquire 和 release 语义。同样,这取决于应用程序实现。gcc 编译器直接在内置函数中使用这些指令,如下列网址所示。

https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html

总结

Ampere 系列处理器正以其持续增加的核心数量不断挑战性能极限,并具备使用锁的多线程应用程序可扩展性的所有要素。使用 LSE,在硬件中提供原子指令以获得更好的锁性能。正如我们在本文所看到的,应用程序开发人员可以通过锁库或正确实现锁定算法来充分利用这些指令。

关于 Ampere Computing

Ampere Computing 是一家现代化半导体企业,致力于塑造云计算的未来,并推出了世界上首款云原生处理器。为可持续云而生,Ampere 云原生处理器兼具最高性能和最佳每瓦性能,助力加速多种云计算应用的交付,为云提供行业领先的性能、能效和可扩展性。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    18261

    浏览量

    222116
  • ARM
    ARM
    +关注

    关注

    134

    文章

    8648

    浏览量

    361756
  • 内存
    +关注

    关注

    8

    文章

    2767

    浏览量

    72753
  • 指令
    +关注

    关注

    1

    文章

    578

    浏览量

    35372
  • Ampere
    +关注

    关注

    1

    文章

    54

    浏览量

    4501
收藏 人收藏

    评论

    相关推荐

    Ampere推出业内首款拥有最多内核数量的云原生处理器系列

    Ampere Altra系列提供了解决各种工作负载的灵活性,并且Ampere正在与生态系统中的伙伴合作,以满足客户的特定需求。
    发表于 06-28 16:44 1369次阅读

    业界首款!Ampere发布有80个核心的ARM处理器

    今天晚上,Ampere发布了Ampere Altra处理器,官方称这是业界首款80核服务器处理器,可为云计算提供强大性能,并且拥有高能效。
    的头像 发表于 03-04 10:11 2404次阅读

    Ampere发布业内首款80核ARM架构64位处理器Altra 并已开始向云服务和边缘计算客户出样

    高性能计算公司Ampere今日发布了业内第一款80核ARM架构64位处理器Altra,其用于服务器、数据中心产品,目标是与Intel、AMD所代表的x86阵营竞争。
    发表于 03-04 11:33 1118次阅读

    Ampere全新推出业界首款80核服务器处理器Ampere Altra处理器

    安晟培半导体科技有限公司(Ampere Computing)于今日正式发布全新一代Ampere Altra处理器,此款产品是业界首款搭载80个内核数量的服务器中央
    发表于 03-05 07:53 1225次阅读

    安晟培半导体Ampere Altra处理器推出,应用于云和边缘计算数据中心中

    3月4日消息,据国外媒体报道,安晟培半导体科技有限公司(Ampere Computing,简称“安晟培半导体”)发布Ampere Altra处理器,这是业界首款搭载80个内核数量的服务
    的头像 发表于 03-04 17:03 3018次阅读

    Ampere® Altra® Max 对比测试数据公布,性能能效双领先

    ,软件架构得以重建,就如同搬进新家时,家具需要因地制宜重新摆放。   2020 年,面向云计算的新时代,Ampere Computing 设计并推出了第一款云原生处理器——80 核 Ampere® 
    的头像 发表于 04-02 11:30 3557次阅读
    <b class='flag-5'>Ampere</b>® <b class='flag-5'>Altra</b>® Max 对比测试数据公布,性能能效双领先

    Ampere Altra处理器实现Arm架构运行虚拟机

     近日,微软推出了基于 Ampere Altra 云原生处理器的 Azure 虚拟机(VM)。
    的头像 发表于 04-10 10:16 3033次阅读

    HPE正式发布搭载Ampere云原生处理器的HPE ProLiant RL300 Gen11平台

    在今年的 HPE Discover 2022 全球峰会上,HPE 宣布正式发布搭载 Ampere AltraAmpere Altra Max 云原生
    的头像 发表于 07-13 11:40 1831次阅读

    云原生处理器给Azure虚拟机带来了哪些优势

    这种极具颠覆性的优势使 Ampere Altra 系列成为现代云基础设施中最具可持续性的处理器
    发表于 09-08 18:22 395次阅读

    Ampere Computing发布全新AmpereOne系列处理器,192个自研核

    2023 年 5 月 19 日,中国北京——Ampere Computing 宣布推出全新 AmpereOne 系列处理器,该处理器拥有多达 192 个单线程
    的头像 发表于 05-19 11:04 897次阅读

    Ampere全新AmpereOne系列处理器,多达192个单线程Ampere

    强调Ampere凭借过去Ampere AltraAmpere Altra Max处理器创建了云
    发表于 05-23 11:44 311次阅读

    Ampere发布AmpereOne系列处理器,单颗处理器支持最高192个物理核心

    AmpereOne出现以前,Ampere Altra系列最多128核心,新的AmpereOne则是从136核起步,最多192核心。所以,AmpereOne可以看做是Ampere
    发表于 06-02 10:43 349次阅读
    <b class='flag-5'>Ampere</b>发布AmpereOne<b class='flag-5'>系列</b><b class='flag-5'>处理器</b>,单颗<b class='flag-5'>处理器</b>支持最高192个物理核心

    优化指南-Ampere® Altra®系列处理器的锁和内存

    让我们先来了解一些基本的问题。Arm 在 Arm v8.2-A 架构中引入了大型系统扩展(Large System Extensions, LSE),它用单个原子指令取代了锁操作的指令序列
    发表于 06-07 17:35 573次阅读
    优化指南-<b class='flag-5'>Ampere</b>® <b class='flag-5'>Altra</b>®<b class='flag-5'>系列</b><b class='flag-5'>处理器</b>的锁和<b class='flag-5'>内存</b>序

    全新AmpereOne系列处理器,一款192核的云原生CPU

    这个基于自研内核打造的产品与之前的产品不会存在任何的兼容问题,因为AmpereOne系列处理器Ampere Altra系列
    发表于 06-08 11:50 597次阅读
    全新AmpereOne<b class='flag-5'>系列</b><b class='flag-5'>处理器</b>,一款192核的云原生CPU

    基于Ampere Altra 系列处理器的一系列平台为 AI 高效赋能

    ,‘芯’未来”的主题,Ampere 在本次活动上展示了基于 Ampere Altra 系列处理器的一系列
    的头像 发表于 09-21 09:13 528次阅读