IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 乱序和屏障 -> 正文阅读

[嵌入式]乱序和屏障

这里的乱序 指的是 编译器乱序,执行乱序 , 不是memory order
这里的屏障 指的是 编译器屏障,内存屏障(在这里用cpu内存屏障来代替)
	// 其中 cpu内存屏障也是 memory order的补丁

cpu 内存屏障可以解决三个问题
	1. 编译器优化导致的乱序
	2. cpu运行优化导致的乱序
	3. 弱 memory order 导致的问题

有人要说了,那 cpu 内存屏障 可以替代 编译器屏障 ,为什么 还要 编译器屏障呢?
	因为 cpu 内存屏障 的代价 比 编译器屏障 大 ,会增加程序运行时间 


硬件及软件技术的变化

1. 编译器的优化
	当优化开关打开时
	编译器会真对不同的cpu 做一些优化
	并且会优化掉编译器认为重复的操作
	
	例如
		情景1
		我连续写了串口的发送寄存器两次,他会优化掉
		我就是想写两次来打印两个字符
		
2. 运行时的优化
	硬件一设计出来就有,无法关闭
	为了 提高 " 流水线 " 性能
	新式处理器可以采用 " 超标量 体系结构 “ 和 ” 乱序执行 " 技术 , 可以在 一个时钟周期 中 并行执行多条指令 ;
	但是 CPU 执行优化会导致 指令乱序执行 , 后面的指令先于前面的指令执行 , 导致 寄存器中的值冲突 ;
	
	例如
		情景1
		我的程序先配置 串口速率寄存器,然后 向 串口发送寄存器 写值
		cpu 发射的时候. 可能串口速率寄存器还没写值 , 但是 串口发送寄存器已经写了一个数了

		情景2 memory order
		我的程序先配置 串口速率寄存器,然后 向 串口发送寄存器 写值
		cpu 发射的时候. 可能串口速率寄存器配了值(效果还没出来,硬件还没处理好这个值), 串口发送寄存器马上就写了一个数.
		

优化带来的问题

1. 编译器优化
	优化后,不是我想要的代码逻辑
	不优化,指令太多,跑的时间太长
	
	诉求 : 不想优化的地方你不许优化
2. 运行时优化
	优化后,先后顺序会搞反.
	不优化,没有充分利用硬件,跑的不够快 ??? 错了,没得选,必须得优化
	
	诉求 : 某些顺序有要求的指令序列,你得按照顺序跑

阻止被优化的技术

编译器内存屏障

1. 编译器优化(-O2 才能打开,不打开默认是不优化.你写什么顺序,就是什么顺序.你写从内存中load,就不会优化到register)
	用编译器的提示指令来处理 // 编译器内存栅栏(编译器)
		1. 交换指令顺序/合并指令
			1.显式 #define barrier() asm volatile("": : :“memory”)
			2.隐式 调用一个函数// 注意 : 不是 inline 一个函数
			3.显式 asm volatile(“yield” ::: “memory”); // armv7及以上架构中可应用
			4.显式 volatile 
		2. 编译器做寄存器的优化,而不再内存中load
			1.显式 #define barrier() asm volatile("": : :“memory”)
			2.隐式 调用一个任意函数// 注意 : 不是 inline 一个函数
			3.显式 asm volatile(“yield” ::: “memory”); // armv7及以上架构中可应用
			4.显式 READ_ONCE // linux 中可应用,当然,你可以移植到你的代码中
			5.显式 volatile 

编译器内存屏障实验代码

https://gitee.com/suweishuai/baremetal
该仓库 做了 基于四个架构(arm32/arm64/rv32/rv64)的 编译器内存优化 编译器内存屏障 练习
优化等级涉及 7种等级
无Ox 等价于 -O0
-Og
-O  等价于-O1
-Os
-O2
-O3
-Ofast
屏障方法涉及 三种
1. 显式 #define barrier() asm volatile("": : :“memory”)
2. 隐式 调用一个函数// 注意 : 不是 inline 一个函数
3. 显式 volatile

CPU 内存屏障

2. 运行时优化(一直存在)
	用架构定义的提示指令来处理 // 内存栅栏(cpu)
		注意 : 这个指令完全是架构定义的,所以不同的架构 实际调用的指令不同
		注意 : 所有的CPU内存屏障封装都隐式包含了编译器屏障
		可以用内嵌汇编的方式调用,但是linux中定义好了一些 cpu内存屏障宏,为什么不用呢?
			smp_wmb smp_rmb smp_mb	

RISCV的CPU内存屏障宏
#define nop()		__asm__ __volatile__ ("nop")

#define RISCV_FENCE(p, s) \
	__asm__ __volatile__ ("fence " #p "," #s : : : "memory")

/* These barriers need to enforce ordering on both devices or memory. */
#define mb()		RISCV_FENCE(iorw,iorw)
#define rmb()		RISCV_FENCE(ir,ir)
#define wmb()		RISCV_FENCE(ow,ow)

/* These barriers do not need to enforce ordering on devices, just memory. */
#define __smp_mb()	RISCV_FENCE(rw,rw)
#define __smp_rmb()	RISCV_FENCE(r,r)
#define __smp_wmb()	RISCV_FENCE(w,w)

ARM的CPU内存屏障宏
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")

#define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)

各个指令集架构的内存屏障指令

riscv
	fence			sync thread
	fence.i  		sync instr & data
	sfence.vma  	virtual memory fence

armv8
	dmb				data memory barrier
	dsb 			data sync barrier
	isb				instruction sync barrier

armv7
	dmb				data memory barrier
					在DMB之后的显示的内存访问执行前,保证所有在DMB指令之前的内存访问完成。
	dsb 			data sync barrier
					等待所有在DSB指令之前的指令完成(之后再执行后续的指令,译注)。
	isb				instruction sync barrier
					清除(flush)流水线,使得所有ISB之后执行的指令都是从cache或内存中获得的(而不是流水线中的)
armv6
	dmb
	dsb
	PrefetchFlush
		The PrefetchFlush instruction flushes the pipeline in the processor,
		so that all instructions following the pipeline flush are fetched 
		from cache or memory after the instruction has been completed.


  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:35:52  更:2022-05-05 11:36:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:04:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码