编译乱序和执行乱序

编译乱序

编译器可以对访存的指令进行乱序,减少逻辑上不必要的访存,以及尽量提高 Cache 命中率和 CPU 的 Load/Store 单元的工作效率。因此在打开编译器优化以后,有时会看到生成的汇编码并没有严格按照代码的逻辑顺序。

解决编译乱序问题,需要通过 barrier() 编译屏障进行。可以在代码中设置 barrier() 屏障,这个屏障可以阻挡编译器的优化。

对于编译器来说,设置编译屏障可以保证屏障前的语句和屏障后的语句不乱“串门”。

在这里,再多说一句:关于解决编译乱序的问题,C 语言 volatile 关键字的作用较弱,它更多的只是避免内存访问合并的行为,对 C 编译器而言,volatile 是暗示除了当前的执行线索以外,其他的执行线索也可能改变内存,所以它的含义是“易变的”。


执行乱序

执行乱序是指即便编译器的二进制指令是顺序排放的,但是,在处理器执行时,后发射的执行还是可能先执行完,这里处理器的 “执行乱序(Out-of-Order Execution)”策略。例如高级的 CPU 可以根据自己缓存的组织特性,将访存的指令重新排序执行,连续地址的访问可能会先执行,因为这样命中率高,有的还允许访存的非阻塞,即如果前面的一条访存指令因为缓存不命中,造成长延时的存储访问时,后面的访存指令可以先执行,以便从缓存中取数。

为了解决这一问题,引入了内存屏障指令。


Linux 内核屏障指令

在 Linux 内核中定义了读写屏障 mb()、读屏障 rmb()、写屏障 wmb()、以及作用于寄存器读写的 __iormb()、__iowmb()这样的屏障 API。

在 Linux 的 I/O 内存读写中,没有 _relaxed 后缀的读写寄存器函数中含有屏障 API。

#define readb_relaxed(c) ({ u8  __v = ioswabb(__raw_readb(c)); __v; })       /* 读8bit */

...

#define readb(a) ({ u8  r_ = readb_relaxed(a); rmb(); r_; })/* 读8bit */

...


使用屏障指令访问外设

当程序访问外设的寄存器时,这些寄存器的访问顺序在 CPU 的逻辑上够不成依赖关系,但是从外设的逻辑角度来讲,可能需要固定的寄存器读写顺序,这个时候,也需要使用 CPU 的内存屏障指令。

MCU乱序执行的原理基于动态流水线的核心思想,即通过硬件的动态调度,来最大化指令级并行性(Instruction-Level Parallelism, ILP)。它允许指令不完全按照程序代码的原始顺序(in-order)执行,而是根据数据的准备情况执行单元的空闲状态,进行乱序执行(Out-of-Order Execution, OoOE)。只要一条指令的操作数准备就绪,它就可以“插队”到前面,越过那些因数据依赖而等待的指令,提前执行[^2]。 乱序执行可以提高指令级并行性,充分利用硬件资源,加快程序的执行速度。因为在传统的顺序执行中,若某条指令因等待操作数而阻塞,后续不依赖该操作数的指令也无法执行,导致硬件资源闲置。而乱序执行打破了这种顺序限制,让准备好的指令先执行,从而提高了整体性能。 然而,乱序执行也带来了一些影响。例如,它可能导致程序的执行结果不符合预期,尤其是在存在数据依赖控制依赖的情况下。数据依赖指的是一条指令的结果作为另一条指令的操作数,乱序执行可能使后一条指令在数据未准备好时就执行;控制依赖则涉及到分支跳转等情况,乱序执行可能改变程序的执行流程。 针对乱序执行带来的问题,可采用以下解决方法: - 编译器优化:编译器编译阶段进行分析,通过插入指令屏障(如内存屏障)等方式,确保指令的执行顺序符合程序逻辑。例如,在有数据依赖的指令之间插入内存屏障,保证前一条指令的结果写入内存后,后一条指令才从内存读取数据。 - 硬件同步机制:硬件层面设置同步机制,如锁步执行、同步指令等。锁步执行是指让多个执行单元按照相同的节奏执行指令,避免乱序执行带来的问题;同步指令则用于强制程序在特定点进行同步,确保指令顺序的正确性。 ```python # 这里只是一个简单示意,并非实际的MCU编程代码 # 假设这是一个模拟指令执行的代码 # 用列表表示指令序列 instructions = ["inst1", "inst2", "inst3", "inst4"] # 模拟乱序执行,根据某种规则改变指令执行顺序 reordered_instructions = ["inst2", "inst1", "inst4", "inst3"] # 执行指令 for inst in reordered_instructions: print(f"Executing {inst}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值