Chapter 13 Memory Ordering

news/2024/7/4 9:58:15

第十三章
内存排序

如果你的代码直接与硬件或在其他核心上执行的代码交互,或者直接加载或写入要执行的指令,或者修改页表,你需要注意内存排序问题。在所有这些情况下,内存排序问题都由相关代码为您处理.
如果您正在编写操作系统内核或设备驱动程序,或者实现管理程序、JIT编译器或多线程库,那么您必须很好地理解ARM架构的内存排序规则。

ARMv8架构使用了一个弱排序的内存模型。一般来说,这意味着内存访问的顺序不需要与加载和存储操作的程序顺序相同。对普通内存的读写可以由硬件重新排序,只受数据依赖关系和显式内存屏障指令的影响。某些情况需要更严格的排序规则.

非常高性能的系统可能会支持一些技术,比如推测内存读取,多个指令发出,或者乱序执行,这些技术和其他技术一起,为硬件内存访问重新排序提供了进一步的可能性:

  1. Multiple issue of instructions 指令多次发出
    一个处理器可以在每个周期发出和执行多条指令,这样按照程序顺序依次执行的指令就可以同时执行。
  2. Out-of-order execution 乱序执行
    许多处理器支持非依赖指令的乱序执行。
    每当一条指令在等待前一条指令的结果时被暂停,处理器就可以执行没有依赖关系的后续指令。
  3. speculation 预测
    当处理器遇到条件指令(如分支)时,它可以在确定是否必须执行特定指令之前推测地开始执行指令。因此,如果情况好转,证明猜测是正确的,结果就会更早出炉。
  4. Speculative loads 预测加载
    如果从可缓存位置读取的load指令被预测地执行,这可能导致缓存线填充和潜在的现有缓存线的回收。
  5. Load and store optimizations 加载和存储优化
    由于对外部内存的读写可能有很长的延迟,处理器可以减少传输的数量,例如,将多个存储合并到一个更大的事务中。
  6. External memory systems 外部内存系统
    在许多复杂的片上系统(SoC)设备中,有许多能够发起传输的代理,以及到被读写的从设备的多条路由。其中一些设备,如DRAM控制器,可能能够接受来自不同主机的同时请求。事务可以被interconnect缓冲,或者重新排序。这意味着来自不同主机的访问可能因此需要不同的周期数来完成,并且可能会相互超越。
  7. Cache coherent multi-core processing 高速缓存连贯多核处理
    在多核处理器中,硬件缓存一致性可以在核之间迁移缓存线。因此,不同的内核可能会以不同的顺序看到缓存内存位置的更新。
  8. Optimizing compilers 优化编译程序
    优化编译器可以重新排序指令,以隐藏延迟或充分利用硬件特性。它通常可以向前移动内存访问,使其更早,并给它更多的时间在需要的值之前完成。

如果您有多个通过共享内存通信的内核,或者以其他方式共享数据,那么内存排序的考虑就变得更加重要。本章讨论几个与多处理(MP)操作和多个执行线程的同步相关的主题。本文还讨论了由体系结构定义的内存类型和规则,以及如何控制它们

13.1 Memory types
ARMv8体系结构定义了两种互斥内存类型。Normal和Device。
除了内存类型之外,属性还提供对缓存性、共享性、访问和执行权限的控制。可共享和缓存属性只属于普通内存。设备区域总是被认为是不可缓存和可外部共享的。对于可缓存的位置,可以使用属性向处理器指示缓存分配策略。
13.1.1 Normal memory
内存里的所有代码和大部分数据区域使用Normal memory。普通内存包括物理内存中的RAM、Flash或ROM区域。这种类型的内存提供了最高的处理器性能,因为它的顺序较弱,并且对处理器的限制较少。处理器可以重新排序、重复和合并访问Normal memory。
然而,处理器必须始终处理由地址依赖引起的危险。
13.1.2 Device memory
您可以为访问可能产生副作用的所有内存区域使用设备内存。设备内存类型对内核施加了更多的限制。不能对Device memory执行Speculative data(推测数据)。这里有一个罕见的例外。如果NEON操作用于从设备内存中读取字节,处理器可能会读取未显式引用的字节,如果它们是对齐的,包含显式引用的一个或多个字节的16字节块。
试图从标记为设备的区域执行代码通常是UNPREDICTABLE(不可预测的)。该实现可以像处理具有普通非缓存属性的内存位置一样处理获取指令,也可以处理权限错误。
有四种不同类型的设备内存,适用不同的规则:
•Device-nGnRnE最严格(相当于ARMv7架构中的强排序内存)。
•Device-nGnRE
•Device-nGRE
•Device-GRE限制最少
字母后缀指的是以下三个属性:

  1. Gathering or non Gathering (G or nG)
    此属性确定是否可以将此内存区域的多个访问合并到单个总线事务中。如果地址被标记为非聚集(nG),那么内存总线上对该位置执行的访问次数和大小必须与代码中显式访问的次数和大小完全匹配。如果地址被标记为gather (G),那么处理器可以将两个字节的写入合并为一个半字的写入。
  2. Re-ordering (R or nR)
    这决定了对同一设备的访问是否可以相互重新排序。如果地址被标记为非重新排序(nR),那么同一块内的访问总是按程序顺序出现在总线上。这个块的大小由实现定义。如果这个块的大小很大,它可以跨越几个表项。在这种情况下,排序规则是针对任何其他也被标记为nR的访问进行的。
  3. Early Write Acknowledgement (E or nE)
    这决定了是否允许处理器和被访问的从设备之间的中间写缓冲区发送写完成的确认。如果地址被标记为非早期写确认(nE),那么写响应必须来自外设。如果地址被标记为早期写确认(E),那么它允许互连逻辑中的缓冲器信号写接受,在写被终端设备实际接收之前。这本质上是给外部存储系统的一条消息。

13.2 Barriers障碍指令
ARM体系结构包括强制访问顺序和访问完成在特定点的障碍指令。

Instruction Synchronization Barrier (ISB) 。指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。
Data Synchronization Barrier (DSB)。数据同步隔离。比 DMB 严格: 仅当所有在它前面的存储器访问操作都执行完毕后,才执行在它后面的指令(亦即任何指令都要等待存储器访 问操作——译者注)
Data Memory Barrier (DMB)。数据存储器隔离。DMB 指令保证: 仅当所有在它前面的存储器访问操作都执行完毕后,才提交(commit)在它后面的存储器访问操作。

13.2.1 One-way barriers
AArch64具有拥有隐式barrier功能的的Load和Store指令。在这些指令前后的加载和存储指令要按顺序执行。
Load-Acquire (LDAR)
所有按照程序顺序在LDAR之后的加载和存储,以及匹配目标地址的共享域,都必须在LDAR之后观察。
Store-Release (STLR)
所有匹配目标地址共享域的STLR前面的load和store必须在STLR前面观察。
也有上述的独家版本,LDAXR和STLXR,可用。

data barrier指令使用限定符来控制哪些共享域可以看到barrier的效果,而LDAR和STLR指令使用访问地址的属性。
在这里插入图片描述
13.2.2 ISB in more detail
ARMv8体系结构中,将上下文定义为系统寄存器的状态。(参考M3任务调度中主要保存替换寄存器的值)。并且将上下文更改操作定义为cache,TLB的分支预测维护操作,或者对系统控制寄存器的更改(例如SCTLR_EL1, TCR_EL1, TTBRn_EL1)。这样的上下文更改操作的效果只能保证在上下文同步事件之后才能看到。

有三种上下文同步事件:
•接受异常。
•从异常返回。
•指令同步障碍(ISB)。

ISB刷新管道,并从缓存或内存中重新获取指令,并确保在ISB之前完成的上下文更改操作的效果对ISB之后的任何指令都是可见的。它还确保在ISB指令之后的任何上下文更改操作只在ISB执行之后生效,而在ISB之前的指令不会看到。但并不是所有对系统寄存器操作都要有ISB。

例:写入CPACR_EL1寄存器的 [20] 位,ISB是一个上下文同步事件,确保之后的指令等待写CRACR_EL生效后执行。
MRS X1, CPACR_EL1
ORR X1, X1, #(0x3 << 20)
MSR CPACR_EL1, X1
ISB

13.2.3 Use of barriers in C code
在单核处理器中,可以使用C11/C++11的序列点,但在多核中,没有什么有效方法,只能使用锁

13.2.4 Non-temporal load and store pair
ARMv8中的一个新概念是非时间加载和存储。这些是执行对寄存器值的读或写的LDNP和STNP指令。

13.3 Memory attributes
系统的内存映射被划分为许多区域。每个区域可能需要不同的内存属性,例如访问权限,包括针对不同权限级别、内存类型和缓存策略的读写权限。代码和数据的功能片段通常在内存映射中组合在一起,每个区域的属性分别控制。该功能由内存管理单元执行。转换表项使MMU硬件能够将虚拟地址转换为物理地址。此外,它们还指定了许多与每个页面相关联的属性。
在这里插入图片描述
•UXN和PXN是执行权限
•AF是访问标志
•SH为可共享属性
•AP为访问权限
NS是安全位,但只在EL3和安全EL1
•Indx是内存间接寄存器MAIR_ELn的索引
为了清晰起见,图中并没有显示所有的位
13.3.1 Cacheable and shareable memory attributes
第十四章多核处理器关于Cacheable内存的更多信息。
shareable属性用于定义一个位置是否与多个核共享。将一个区域标记为不可共享意味着它只被这个核心使用,而将其标记为内部可共享或外部可共享,或两者兼备,则意味着该位置与其他观察者共享,例如,GPU或DMA设备可能被视为另一个观察者。同样,内部和外部的划分由实现定义。这些属性的架构定义是,它们使我们能够定义一组观察者,这些观察者的共享性属性使数据或统一缓存对数据访问透明。
这意味着系统提供了硬件一致性管理,以便在内部可共享域中的两个内核必须看到标记为内部可共享的位置的一致性副本。如果一个处理器或系统中的其他主处理器不支持一致性,那么它必须将可共享区域视为不可缓存的。
在这里插入图片描述
缓存一致性硬件有一定的开销。数据内存访问会比其他方式花费更长的时间和更多的能量。这种开销可以通过在更少数量的主机之间保持一致性,并确保它们在硅中物理上接近而最小化。出于这个原因,体系结构将系统划分为多个域,这样就可以将开销限制在那些需要一致性的位置。(域,这个概念在操作系统中有提到)
Non-shareable
这表示只能由单个处理器或其他代理访问的内存,因此内存访问永远不需要与其他处理器同步。该域通常不用于SMP系统。
Inner shareable
这表示一个可由多个处理器共享的可共享域,但不一定是系统中的所有代理。一个系统可能有多个内部共享域。影响一个内部可共享域的操作不会影响系统中其他内部可共享域。这种域的一个例子可能是四核Cortex-A57集群。
Outer shareable
外部可共享(OSH)域重排序由多个代理共享,可以由一个或多个内部可共享域组成。影响外部可共享域的操作也会隐式地影响其中的所有内部可共享域。
然而,它在其他方面并不表现为内部可共享操作。
Full system
对全系统(SY)的操作会影响系统中所有的观察者。


http://www.niftyadmin.cn/n/3172428.html

相关文章

Docker mysql 和 flask容器连接 bug解决

我是用的 --linkcontainer_name:aka方法连接的两个容器&#xff0c;所以在使用SQLAlchemy连接mysql的时候&#xff0c;需要使用aka别名作为IP地址&#xff0c;如下所示。 <user>:<passwd>aka:<port>/<database>Docker 会把aka转化成mysql容器的地址&a…

MD5加密函数实现

2019独角兽企业重金招聘Python工程师标准>>> 代码如下&#xff1a; import java.security.MessageDigest; public class MD5Util {/*** * MD5加密 生成32位md5码* param 待加密字符串* return 返回32位md5码*/public static String md5Encode(String inStr) throws …

Linux内核设计与实现笔记

第3章 进程管理 进程 进程描述符及任务结构 分配进程描述符&#xff0c;通过slab分配器分配task_struct&#xff0c;达到对象复用和缓存着色的目的 task_struct thread_info 每个任务的thread_info结构在他的内核栈的尾端分配&#xff0c;结构中task域中存放的是指向该任务task…

顺序表的个人心得

为什么要有顺序表&#xff1f; 为了有序存储连续的数据。顺序表存储&#xff1a;开辟连续的内存空间&#xff0c;空间里保存真实数据的引用地址&#xff0c;因为地址固定存储四个字节&#xff0c;可以让当前数据结构产生一种规律&#xff0c;不管访问哪个元素&#xff0c;用开始…

day4-用户授权

重置数据库员密码 mysqladmin -hlocalhost -uroot -p password "" 恢复数据库管理员密码 [rootlocalhost ~]# /etc/init.d/mysqld stop [rootlocalhost ~]# /etc/init.d/mysqld start --skip-grant-table mysql>update mysql.user set passwordpassword("新密…

17.动态规划入门

一、算法介绍 1.简介 本次课我们将介绍介绍动态规划&#xff08;Dynamic Programming, DP&#xff09;及其解决的问题、根据其设计的算法及优化。 动态规划是编程解题的一种重要手段&#xff0c;它是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规…

Linux设备驱动程序学习笔记——第七章时间、延迟及延缓操作

Linux设备驱动程序学习笔记 第七章时间、延迟及延缓操作 一、度量时间差 内核通过定时器中断来跟踪时间流 时钟中断由系统定时硬件以周期性的间隔产生&#xff0c;这个间隔由内核根据HZ的值设定&#xff0c;HZ是一个与体系结构相关的常数&#xff0c;定义在<linux/param.h…

Linux设备驱动程序学习笔记——第八章分配内存

Linux设备驱动程序学习笔记 第八章分配内存 一、kmalloc函数的内幕 &#xff08;1&#xff09;flags参数 //kmalloc原型 #include<linux/slab.h> void *kmalloc(size_t size, int flags);//flags分配标志&#xff0c;最常用的是GFP_FERNEL分配标志&#xff1a; GFP_A…