CPU缓存和内存屏障

Wesley13
• 阅读 485

CPU性能优化手段-缓存

为了提高程序运行的性能,现代CPU在很多方面对程序进行了优化。 例如:CPU高速缓存。尽可能地避免处理器访问主内存的时间开销,处理器大多会利用缓存(cache)以提高性能。

CPU缓存和内存屏障

多级缓存

L1 Cache(一级缓存)是CPU第一层高速缓存,分为数据缓存和指令缓存。一般服务器CPU的L1缓存的容量通常在32-4096KB。

L2由于L1级高速缓存容量的限制,为了再次提高CPU的运算速度,在CPU外部放置-高速存储器,即二级缓存。

L3现在的都是内置的。而它的实际作用即是,L3缓存的应用可以进一步降低内存延迟,同时提升大数据量计算时处理器的性能。具有较大L3缓存的处理器提供更有效的文件系统缓存行为及较短消息和处理器队列长度。一般是多核共享一个L3缓存!

CPU在读取数据时,先在L1中寻找,再从L2寻找,再从L3寻找,然后是内存,再后是外存储器。

缓存同步协议

多CPU读取同样的数据进行缓存,进行不同运算之后,最终写入主内存以哪个CPU为准?

在这种高速缓存回写的场景下,有一个缓存一致性协议多数CPU厂商对它进行了实现。

MESI协议,它规定每条缓存有个状态位,同时定义了下面四个状态:

  • **修改态(Modified)**-此cache行已被修改过(脏行),内容已不同于主存,为此cache专有;
  • **专有态(Exclusive)**-此cache行内容同于主存,但不出现于其它cache中;
  • **共享态(Shared)**-此cache行内容同于主存,但也出现于其它cache中;
  • **无效态(Invalid)**-此cache行内容无效(空行)。

多处理器,单个CPU对缓存中数据进行了改动,需要通知给其它CPU。也就是意味着,CPU处理要控制自己的读写操作,还要监听其他CPU发出的通知,从而保证最终一致。

CPU性能优化手段-运行时指令重排

CPU缓存和内存屏障

指令重排的场景:当CPU写缓存时发现缓存区块正被其他CPU占用,为了提高CPU处理性能,可能将后面的读缓存命令优先执行。

并非随便重排,需要遵守as-if-serial语义

as-if-serial语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,runtime和处理器都必须遵守as-if-serial语义。也就是说:编译器和处理器不会对存在数据依赖关系的操作做重排序。

两个问题

1、CPU高速缓存下有一个问题:

缓存中数据与主内存的数据并不是实时同步的,各CPU(或CPU核心)间缓存的数据也不是实时同步。

在同一个时间点,各CPU所看到同一内存地址的数据的值可能是不一致的。

2、CPU执行指令重排序优化下有一个问题:

虽然遵守了as-if-serial语义,单仅在单CPU自己执行的情况下能保证结果正确。多核多线程中,指令逻辑无法分辨因果关联,可能出现乱序执行,导致程序运行结果错误。

内存屏障

处理器提供了两个内存屏障指令(Memory Barrier)用于解决上述两个问题:

写内存屏障(Store Memory Barrier):在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,让其他线程可见。强制写入主内存,这种显示调用,CPU就不会因为性能考虑而去对指令重排。

读内存屏障(Load Memory Barrier):在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从主内存加载数据。强制读取主内存内容,让CPU缓存与主内存保持一致,避免了缓存导致的一致性问题。

CPU缓存和内存屏障

点赞
收藏
评论区
推荐文章
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录 问题 用navicat导入数据时,报错: 原因这是因为当前的MySQL不支持datetime为0的情况。 解决修改sql\mode: sql\mode:SQL Mode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。 全局s
Wesley13 Wesley13
11个月前
CPU 缓存一致性协议 MESI
CPU 高速缓存(Cache Memory) ---------------------- ### CPU 为何要有高速缓存 CPU 在摩尔定律的指导下以每 18 个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及 CPU。这就造成了高性能能的内存和硬盘价格及其昂贵。然而 CPU 的高度运算需要高速的数据。为了解决这个问题,CPU 厂商在 CPU
Stella981 Stella981
11个月前
Android So动态加载 优雅实现与原理分析
> 背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载. ![](https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png) 点击上方“蓝字”关注我
Stella981 Stella981
11个月前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有`time`,和`datetime`两个,本文先说`time`模块。 ### 关于时间戳的几个概念 * 时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。 * 时间元组(`struct_time`),包含9个元素。  `time.struct_time(tm_y
Wesley13 Wesley13
11个月前
java高并发(三)并发编程的基础
CPU多级缓存 ======= 为什么需要CPU缓存? ----------- 原因是,CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题。 CPU缓存有什么意义? ----------- * 时间局部性:如果某个数据被访问,那么在不久的将
Wesley13 Wesley13
11个月前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表: **时辰** **时间** **24时制** 子时 深夜 11:00 - 凌晨 01:00 23:00 - 01 :00 丑时 上午 01:00 - 上午 03:00 01:00 - 03 :00 寅时 上午 03:00 - 上午 0
Wesley13 Wesley13
11个月前
MySQL查询按照指定规则排序
1.按照指定(单个)字段排序 select * from table_name order id desc; 2.按照指定(多个)字段排序 select * from table_name order id desc,status desc; 3.按照指定字段和规则排序 selec
Stella981 Stella981
11个月前
Angular material mat
Icon Icon Name mat-icon code _add\_comment_ add comment icon <mat-icon> add\_comment</mat-icon> _attach\_file_ attach file icon <mat-icon> attach\_file</mat-icon> _attach\
Wesley13 Wesley13
11个月前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
#### 背景描述 # Time: 2019-01-24T00:08:14.705724+08:00 # User@Host: **[**] @ [**] Id: ** # Schema: sentrymeta Last_errno: 0 Killed: 0 # Query_time: 0.315758 Lock_
helloworld_34035044 helloworld_34035044
2个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。 uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid() 或 uuid(sep)参数说明:sep 布尔值,生成的uuid中是否包含分隔符'',缺省为