cpu缓存与多线程
一、cpu缓存结构
CPU速度远高于内存(即如果只考虑CPU和内存因素,程序的性能常常受到内存访问速度的限制,内存访问和运行),为了协调CPU和内存在速度上的差异,在CPU中增加了高速缓存。和计算机存储金字塔结构类似,高速缓存也可以按照金字塔结构,从下到上越接近CPU速度越快,同时容量也越小。现在大部分的处理器都有二级或者三级缓存,从下到上依次为 L3 cache, L2 cache, L1 cache. 缓存又可以分为指令缓存和数据缓存,指令缓存用来缓存程序的代码,数据缓存用来缓存程序的数据。
单核CPU只含有一套L1,L2,L3缓存;如果CPU含有多个核心,即多核CPU,则每个核心都含有一套L1(甚至和L2)缓存,而共享L3(或者和L2)缓存。多CPU,每个CPU都相互独立,拥有自己的缓存,CPU之间无法共享缓存。 下图为一个单CPU双核的缓存结构。
缓存行 cache line
缓存行时缓存和内存交换数据的最小单位,一般为64字节。即每次缓存和内存之间进行数据交换的时候,都是以字节对齐的连续64字节的内存块整个进行。
缓存访问
没有缓存的结构中,CPU执行进程的时候,使用虚拟地址,虚拟地址通过MMU翻译为物理地址,映射到内存中;在有缓存的结构中,CPU访问数据先查找缓存中是否存在该数据,这可以通过数据在进程中的虚拟地址去到缓存中查找,也可以通过该数据在内存中的物理地址去到缓存中查找。
因此,缓存中的数据既可以通过数据在进程空间中的虚拟地址检索,也可以通过数据的实际内存物理地址来检索。如果通过进程空间中的虚拟地址,那么多个不同进程可能含有相同的虚拟地址,因此实际中还需要在缓存行中添加 ASID(address space identifier) the hardware version of a process ID,这样CPU在运行不同进程的时候,就可以通过 虚拟地址+ASID 在cache中进行查找;
如果缓存通过物理地址来检索,那么需要MMU介于CPU和cache中间来进行地址的翻译,这样就降低了cache查找的速率,因此一般 L1 cache不能通过物理地址检索,而是通过虚拟地址,由CPU直接访问。而L2,L3 cache可以通过物理内存地址检索。
TLB 快表
MMU进行虚拟地址到物理地址的映射,通过页表将虚拟地址翻译为物理地址。TLB位于MMU内部,不需要经过页表就可以将虚拟地址转换为物理地址,速度更快。
每一个TLB寄存器的每个条目包含一个页面的信息:有效位,虚页面号,修改位,保护码,和页面所在的物理页面号,它们和页面表中的表项一一对应。
MMU在翻译的时候,先查看虚拟地址的虚拟页面号是否存在TLB(并行的查找)中,如果存在,且没有违背读写权限限制,则直接给出TLB中的物理页面号;若在TLB中不存在,则进行常规的页表的查找,然后从TLB中淘汰一个条目,并更新为刚刚查找的页面。
多线程场景下的缓存
在单线程模式下,一块内存只对应一个cpu核心的缓存,且只被一个线程访问。缓存独占,不会出现访问冲突等问题。
在多线程模式下,一个CPU,且CPU单核,进程中的多个线程会同时访问进程中的共享数据,CPU将某块内存加载到缓存后,不同线程在访问相同的物理地址的时候,都会映射到相同的缓存位置,这样即使发生线程的切换,缓存仍然不会失效。但由于任何时刻只能有一个线程在执行,因此不会出现缓存访问冲突。当然,由于CPU内部寄存器的存在,会有多线程下的 A++ 非原子性语句导致的问题。
(
A++ ==>
reg = (&A);
reg ++;
(&A) = reg;
在发生线程切换的时候,线程使用的内部寄存器会被作为现场进行保存。
)
多线程模式下,一个CPU,且CPU有多核,每个核都至少有一个L1 cache。多个线程访问进程中的某个共享内存,且这多个线程分别在不同的核心上执行,则每个核心都会在各自的caehe中保留一份共享内存的缓冲。由于多核可以做到真并行,可能会出现多个线程同时写各自的cache,
因此CPU有“缓存一致性”原则,即每个处理器(核)都会通过嗅探在总线上传播的数据来检查自己的缓存值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器(核)。因此,我们经常看到在多核多线程的场景下,在声明变量时候使用volatile,volatile变量要求在更新了缓存之后立即写入到系统内存,而非volatile变量,则是CPU修改缓存,缓存在适当的识货(不知道什么时候)将缓存数据写入内存。写入内存的操作会出发其他处理器(核)将自己已经缓存的那块正在被写入的内存失效,并在下次需要使用到该内存的时候重新从内存读取。
False Sharing(伪共享)
由于缓存按照最小单位缓存行进行和内存交互,缓存行一般为64字节。内存中的连续64字节会被加载到一个缓存行中。当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。
如上图所示,X和Y被放在同一缓存行中,当core1 修改x的时候,为了线程间可见性,需要锁定缓存行;此时core2中的缓存行也跟着失效;同样,core2中修改y时候,也需要锁定缓存行,core1中的缓存行也跟着失效。影响效率。
cpu缓存与多线程的更多相关文章
- python GIL 全局锁,多核cpu下的多线程性能究竟如何?
python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现 ...
- C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI
目录 1. 前言2 2. 结论2 3. volatile应用场景3 4. 内存屏障(Memory Barrier)4 5. setjmp和longjmp4 1) 结果1(非优化编译:g++ -g -o ...
- 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程
许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...
- 为什么CPU缓存会分为一级缓存L1、L2、L3?有什么意义?
https://baijiahao.baidu.com/s?id=1598811284058671259&wfr=spider&for=pc 简介:CPU缓存是CPU一个重要的组成部分 ...
- 从Java视角理解CPU缓存和伪共享
转载自:http://ifeve.com/from-javaeye-cpu-cache/ http://ifeve.com/from-javaeye-false-shari ...
- CPU缓存和内存屏障
CPU性能优化手段 - 缓存 为了提高程序的运行性能, 现代CPU在很多方面对程序进行了优化例如: CPU高速缓存, 尽可能的避免处理器访问主内存的时间开销, 处理器大多会利用缓存以提高性能 多级缓存 ...
- JMM内存模型、CPU缓存一致性原则(MESI)、指令重排、as-if-serial、happen-before原则
JMM三大特性原子性 汇编指令 --原子比较和交换在底层的支持 cmp-chxg 总线加锁机制 Synchronized Lock锁机制 public class VolatileAtomicSamp ...
- 【Java并发编程】从CPU缓存模型到JMM来理解volatile关键字
目录 并发编程三大特性 原子性 可见性 有序性 CPU缓存模型是什么 高速缓存为何出现? 缓存一致性问题 如何解决缓存不一致 JMM内存模型是什么 JMM的规定 Java对三大特性的保证 原子性 可见 ...
- 与程序员相关的CPU缓存知识
本文转载自与程序员相关的CPU缓存知识 基础知识 首先,我们都知道现在的CPU多核技术,都会有几级缓存,老的CPU会有两级内存(L1和L2),新的CPU会有三级内存(L1,L2,L3 ),如下图所示: ...
随机推荐
- 使用NPOI随意创建Excel(含下拉列表)
//创建工作簿 HSSFWorkbook ssfworkbook = new HSSFWorkbook(); //创建工作表(页) HSSFSheet sheet1 = ssfworkbook.Cre ...
- InheritableThreadLocal原理
转载:https://github.com/pzxwhc/MineKnowContainer/issues/20 介绍 InheritableThreadLocal 之前,假设对 ThreadLoca ...
- thinkphp隐藏中url的index.php
在本地进行测试 1.修改apache配置文件将如下代码#去掉 #LoadModule rewrite_module modules/mod_rewrite.so 在index.php 目录下新建文 ...
- jQuery 一些小技巧
1. 返回顶部按钮 可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. // Back to top ...
- 第四课 Activity
1.Activity生命周期 1.1 创建-->启动-->获取焦点-->running-->失去焦点-->停止-->销毁.(一个正常activity的生命周期) 1 ...
- nginx fastcgi 超时问题解决记录
在网站后台导数据时,出现超时的情况.经过网上查找资料和试验 主要在下面几个配置的限制 1.php配置 第一种:set_time_limit(0); 永不过期 第二种: php.ini max_ex ...
- 【leetcode❤python】21. Merge Two Sorted Lists
#-*- coding: UTF-8 -*- # Definition for singly-linked list.# class ListNode(object):# def __init ...
- 如何选择正确的DevOps工具
坦白的讲:世界上没有哪种工具能够像DevOps这么神奇(或敏捷,或精益).DevOps在开发和运营团队之间建立了完美的合作与沟通,因此与其说这是一种神奇的工具,不如说是一种文化的转变. 然而,团队之间 ...
- SpringMVC 服务器端验证
1.导入JSR303验证类库Jar包2.在MVC的配置文件中添加<mvc:annotation-driven/>的配置3.在MVC的配置文件中添加验证器的配置4.在接收表单数据的类中添加验 ...
- JQuery 选中Radio
<tr> <td> <input type="radio" name="rdb" value="启用" che ...