CPU缓存和内存屏障

CPU性能优化手段 - 缓存

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

多级缓存

L1 Cache (一级缓存)是CPU第一层高速缓存, 分为数据缓存和指令缓存, 一般服务器CPU的L1缓存的容量通常在32-4096kb
L2 Cache (二级缓存) 由于L1高速缓存的容量限制, 为了再次提高CPU的运算速度, 在CPU外部放置一高速缓存存储器, 即二级缓存
L3 Cache(三级缓存)现在都是内置的, 而它的实际作用既是, 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处理性能, 可能将后面的读缓存命令优先执行.
当然也并非随便重排, 需要遵循as-if-serial语义
as-if-serial语义的意思指: 不管怎么重排序, 程序的执行结果不能被改变
编译器, runtime和处理器都必须遵守as-if-serial语义, 也就是说, 编译器和处理器不会对存在数据依赖关系的操作做重排序

两个问题

  1. CPU高速缓存下有一个问题:
    缓存中的数据与主内存的数据并不是实时同步的, 各CPU间缓存的数据也不是实时同步. 在同一时间点, 各CPU所看到的同一内存地址的数据的值可能是不一致的.
  2. CPU执行指令重排序优化的一个问题:
    虽然遵守了as-if-serial语义, 但仅在单CPU自己执行的情况下能保证结果正确. 多核多线程中, 指令逻辑无法分辨因果关联, 可能出现乱序执行, 导致程序运行结果错误

解决方法 - 内存屏障

处理器提供了两个内存屏障指令(Memory Barrier)用于解决上述两个问题:
写内存屏障(Store Memory Barrier): 在指令后插入Store Barrier, 能让写入缓存中的最新数据更新写入主内存, 让其他线程可见
强制写入主内存, 这种显示调用, CPU就不会因为性能考虑而进行指令重排

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

?

原文地址:https://www.cnblogs.com/coding-diary/p/11153774.html

时间: 2024-10-04 01:56:14

CPU缓存和内存屏障的相关文章

内存屏障

原文地址:http://ifeve.com/memory-barriers-or-fences/ 本文我将和大家讨论并发编程中最基础的一项技术:内存屏障或内存栅栏,也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术. CPU使用了很多优化技术来实现一个目标:CPU执行单元的速度要远超主存访问速度.在上一篇文章 “Write Combing (合并写)”中我已经介绍了其中的一项技术.CPU避免内存访问延迟最常见的技术是将指令管道化,然后尽量重排这些管道的执行以最大化利用缓存,从而把

LINUX内核内存屏障

================= ================= By: David Howells <[email protected]> Paul E. McKenney <[email protected]> 译: kouu <[email protected]> 出处: Linux内核文档 -- Documentation/memory-barriers.txt 文件夹: (*) 内存訪问抽象模型. - 操作设备. - 保证. (*) 什么是内存屏障? -

volatile关键字?MESI协议?指令重排?内存屏障?这都是啥玩意

一.摘要 三级缓存,MESI缓存一致性协议,指令重排,内存屏障,JMM,volatile.单拿一个出来,想必大家对这些概念应该有一定了解.但是这些东西有什么必然的联系,或者他们之间究竟有什么前世今生想必是困扰大家的一个问题.为什么有了MESI协议,我们还需要volatile?内存屏障的由来?指令重排带来的问题?下面我们通过分析每一个技术的由来,以及带来的负面影响,跟大家探讨一下这些技术之间的联系.具体每个关键词相关文章也很多不再赘述,只谈个人理解. 二.三级缓存篇 1,三级缓存的由来 CPU的发

原子操作&amp;优化和内存屏障

原子操作 假定运行在两个CPU上的两个内核控制路径试图执行非原子操作同时"读-修改-写"同一存储器单元.首先,两个CPU都试图读同一单元,但是存储器仲裁器插手,只允许其中的一个访问而让另一个延迟.然而,当第一个读操作已经完成后,延迟的CPU从那个存储器单元正好读到同一个(旧)值.然后,两个CPU都试图向那个存储器单元写一新值,总线存储器访问再一次被存储器仲裁器串行化,最终,两个写操作都成功.但是,全局的结果是不对的,因为两个CPU写入同一(新)值.因此,两个交错的"读-修改-

内存屏障和volatile内存语义的实现

趁周末,把以前的书拿出来,再翻一番,顺便做个笔记: 内存屏障:用来控制和规范cpu对内存操作的顺序的cpu指令. 内存屏障列表: 1.loadload:确保"前者数据装载"先于"后者装载指令": 2.storestore:确保"前者数据"先于"后者数据"刷入系统内存,且,"前者刷入系统内存的数据"对"后者是可见的": 3.loadstore:确保"前者装载数据"先于&

linux内核同步之每CPU变量、原子操作、内存屏障、自旋锁【转】

转自:http://blog.csdn.net/goodluckwhh/article/details/9005585 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一每CPU变量 二原子操作 三优化和内存屏障 四自旋锁 自旋锁 自旋锁的数据结构和宏函数 读写自旋锁 读写自旋锁的相关函数 linux内核中的各种“任务”都能看到内核地址空间,因而它们之间也需要同步和互斥.linux内核支持的同步/互斥手段包括: 技术 功能 作用范围 每CPU变量 为每个CPU复制一份数据

CPU缓存是位于CPU与内存之间的临时数据交换器,它的容量比内存小的多但是交换速度却比内存要快得多。CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上

一.什么是CPU缓存 1. CPU缓存的来历 众所周知,CPU是计算机的大脑,它负责执行程序的指令,而内存负责存数据, 包括程序自身的数据.在很多年前,CPU的频率与内存总线的频率在同一层面上.内存的访问速度仅比寄存器慢一些.但是,这一局面在上世纪90年代被打破了.CPU的频率大大提升,但内存总线的频率与内存芯片的性能却没有得到成比例的提升.并不是因为造不出更快的内存,只是因为太贵了.内存如果要达到目前CPU那样的速度,那么它的造价恐怕要贵上好几个数量级.所以,CPU的运算速度要比内存读写速度快

技术向|内存屏障(Memory Barriers)--Runtime Time

在讨论CPU的内存屏障之前,让我们先了解一下缓存结构. 缓存(Cache)结构简介 现代计算机系统的缓存结构粗略如下: 每个CPU都有自己的缓存. 缓存(Cache)分为又分多个级别. 一级缓存L1的访问非常接近一个cpu周期(cycles),二级缓存L2的存取可能就要大概10个周期了. 缓存和内存交换数据的最小单元叫Cache Line.它是一个固定长度的块,可能是16到256字节(bytes). 比如一个32位的CPU有1M的缓存,每个Cache Line的大小是64bytes.那么这个缓存

Linux内核中的内存屏障解析

缓存一致性 之前一直认为linux中很多东西是用来保证缓存一致性的,其实不是.缓存一致性绝大部分是靠硬件机制实现的,只有在带lock前缀的指令执行时才与cache有一点关系.(这话说得绝对,但我目前看来就是这样)我们更多的时候是为了保证顺序一致性. 所谓缓存一致性,就是在多处理器系统中,每个cpu都有自己的L1 cache.很可能两个不同cpu的L1 cache中缓存的是同一片内存的内容,如果一个cpu更改了自己被缓存的内容,它要保证另一个cpu读这块数据时也要读到这个最新的.不过你不要担心,这