CPU 的五级流水线
Contents
现代C++的内存模型。–神文
自底向上理解memory_order。
大白话C++之:一文搞懂C++多线程内存模型(Memory Order)。
时钟周期也称为振荡周期,定义为时钟频率的倒数。时钟周期是计算机中最基本的、最小的时间单位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期表示了SDRAM所能运行的最高频率。
如果没有Cache,CPU每执行一条指令,都要去内存取下一条,而执行一条指令也就几个时钟周期(几ns),而取指令却要上百个时钟周期,这将导致CPU大部分时间都在等待状态,进而导致执行效率低下。
C++ 内存模型(Memory Model)定义了程序在多线程环境中如何访问和共享内存,它为程序的正确性、并发性和可移植性提供了保证。C++ 内存模型主要通过原子操作、内存序列(Memory Ordering)、同步和锁等机制来规范线程之间的内存访问行为。
CPU 的五级流水线
CPU 将指令执行分解成5个部分,分别是:IF 取指令,ID 译码,EX 执行,MEM 访问内存,WB 写回。
内存顺序模型 | 描述 |
---|---|
memory_order_seq_cst | 顺序一致(sequentially consistent ordering),只有该值满足sC顺序一致性,原子操作默认使用该值。 |
memory_order_relaxed | 松散(relaxed ordering) |
memory_order_consume | 获取发布(acquire-release ordering) |
memory_order_acquire | 获取发布(acquire-release ordering) |
memory_order_release | 获取发布(acquire-release ordering) |
memory_order_acq_rel | 获取发布(acquire-release ordering) |
与编译器优化有关:
|
|
|
|
|
|
对于内存读写来说,读写顺序需要严格按照代码顺序,即要求如下(符号<p
表示程序代码顺序,符号<m
表示内存的读写顺序):
|
|
顺序一致这么严格,其显然会限制编译器和CPU的优化,所以业界提出了很多宽松的模型,例如在X86中使用的TSO(Total Store Order)便允许某些条件下的重排。
memory_order_acquire
:对于使用该枚举值的load操作,不允许该load之后的操作重排到load之前。memory_order_release
:使用该枚举值的store操作,不允许store之前的操作重排到store之后。
现代C++(包括Java)都是使用了SC-DRF(Sequential consistency for data race free)。在SC-DRF模型下,程序员只要不写出Race Condition的代码,编译器和CPU便能保证程序的执行结果与顺序一致相同。因而,内存模型就如同程序员与编译器/CPU之间的契约,需要彼此遵守承诺。C++的内存模型默认为SC-DRF,此外还支持更宽松的非SC-DRF的模型。
C++内存模型借鉴lock/unlock,引入了两个等效的概念,Acquire(类似lock)和Release(类似unlock),这两个都是单方向的屏障(One-way Barriers: acquire barrier, release barrier)。