Cache 总结

这一文,让我们分析一下,《浅谈 Cache》 一文中的奇怪现象,其实现在来看也并不奇怪了。

在什么情况下 r1 和 r2 都为 0 呢?

仔细看代码,你会发现,两个线程分别被运行在不同的 CPU 核上,并且在线程开始的阶段还使用了一个随机数,是为了让两个线程能尽量同时运行。

假设 CPU0 运行:

x = 1;

r1 = y;

CPU1 运行:

y = 1;

r2 = x;

如果下面的情况发生:

x 在 CPU1 的 Cache 中。 y 在 CPU0 的 Cache 中。

1. CPU0 执行 x = 1, cache miss, 发送 "read invalidate" 消息,并把 x 的值 1 存入 Store Buffer, 开始执行 r1 = y, Cache 命中,r1 为 0;

2. CPU1 执行 y = 1,cache miss, 发送 "read invalidate" 消息,并把 y 的值 1 存入 Store Buffer, 开始执行 r2 = x,Cache 命中,r2 为 0;

3. CPU0 和 CPU1 各自收到了对方的消息,并作出回应,x 和 y 的值均应用到 Cache 中,且都为 1;

主函数收到信号,比较 r1 和 r2 的值,奇迹发生了。

如果你知道我讲的这些细节,就会发现,其实这并不是奇怪了。那么如果解决这个问题呢?

其实答案就很简单了,要么让两个线程运行在同一个核心上,要么在两个语句之间加上内存屏障,经验证,问题解决了。

题外篇:

在不同 CPU 架构下,对内存的乱序访问其实是不同的,一般的内存乱序分为以下四种:

LoadStore, LoadLoad, StoreStore, StoreLoad。并且 X86 下只会出现 StoreLoad 乱序,也就是上面的例子,我的 CPU 是 X86 的,所以出现了这种情况,由此可知,其实 X86 内存乱序访问的还不算太厉害。

简单解释一下,x = 1,为 Store, 读取 y 的过程为 Load,所以 Load 指令在 X86 下允许在 Store 还未更新到 Cache 中之前被执行。

走出一个误区,内存乱序访问与 CPU 乱序执行(Out of Order,即 OOO)不同。

早期的处理器为有序处理器(In-order processors),有序处理器处理指令通常有以下几步:

1. 指令获取

2. 如果指令的输入操作对象(input operands)可用(例如已经在寄存器中了),则将此指令分发到适当的功能单元中。如果一个或者多个操作对象不可用(通常是由于需要从内存中获取),则处理器会等待直到它们可用;

3. 指令被适当的功能单元执行

4. 功能单元将结果写回寄存器堆(Register file,一个 CPU 中的一组寄存器)

相比之下,乱序处理器(Out-of-order processors)处理指令通常有以下几步:

1. 指令获取

2. 指令被分发到指令队列

3. 指令在指令队列中等待,直到输入操作对象可用(一旦输入操作对象可用,指令就可以离开队列,即便更早的指令未被执行)

4. 指令被分配到适当的功能单元并执行

5. 执行结果被放入队列(而不立即写入寄存器堆)

只有所有更早请求执行的指令的执行结果被写入寄存器堆后,指令执行的结果才被写入寄存器堆(执行结果重排序,让执行看起来是有序的)

从上面的执行过程可以看出,乱序执行相比有序执行能够避免等待不可用的操作对象(有序执行的第二步)从而提高了效率。现代的机器上,处理器运行的速度比内存快很多,有序处理器花在等待可用数据的时间里已经可以处理大量指令了。

现在思考一下乱序处理器处理指令的过程,我们能得到几个结论:

对于单个 CPU 指令获取是有序的(通过队列实现)

对于单个 CPU 指令执行结果也是有序返回寄存器堆的(通过队列实现)

由此可知,在单 CPU 上,不考虑编译器优化导致乱序的前提下,多线程执行不存在内存乱序访问的问题

CPU 虽然是乱序执行,但是是顺序流出结果,在我们看来,乱序执行对我们来讲是透明的,我们看到的结果和指令顺序是一样的。

时间: 2024-08-26 09:37:08

Cache 总结的相关文章

centos7开机无法进入图形界面,出现sda assuming drive cache write through的一个解决方案

centos7开机无法进入图形界面,出现sda assuming drive cache write through.no valid rapl domains found in package之类信息. 这个问题是我在VMware里面操作出现的,原因是我在使用虚拟机和实体机之间文件共享功能时,centos系统无法出现hgfs文件夹, 为了解决hgfs的不出现问题,我参考了如下帖子: http://blog.csdn.net/cindy_cheng/article/details/5045697

Linux内存学习之buffer和cache的区别详解

本文和大家分享的主要是linux 中 内存buffer 和 cache 的区别相关内容,一起来看看吧,希望对大家 学习linux有所帮助. 细心的朋友会注意到, 当你在 linux 下频繁存取文件后 , 物理内存会很快被用光 , 当程序结束后 , 内存不会被正常释放 , 而是一直作为 caching. 这个问题 , 貌似有不少人在问 , 不过都没有看到有什么很好解决的办法 . 那么我来谈谈这个问题 . 先来说说free 命令 [[email protected] ~]# free -m tota

linux 清除内存和Cache方法

Linux下释放内存和缓存方法 $ free -m 运行sync将cache的内容写回硬盘 $ sync #格式:sync 强制将内存中的文件缓冲内容写到磁盘. 通过修改proc系统的drop_caches清理free的cache $ echo 3 > /proc/sys/vm/drop_caches $ free -m 仅清除页面缓存(PageCache) # echo 1 > /proc/sys/vm/drop_caches 清除目录项和inode # echo 2 > /proc/

Linux中的Buffer 与 Cache

A buffer is something that has yet to be "written" to disk.       A cache is something that has been "read" from the disk and stored for later use. 缓存(cache)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘.其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最

ceph cache pool配置

0.引入 本文介绍如何配置cache pool tiering. cache pool的作用是提供可扩展的cache,用来缓存ceph的热点数据或者直接用来作为高速pool.如何建立一个cache pool:首先利用ssd盘做一个虚拟的bucket tree, 然后创建一个cache pool,设置其crush映射rule和相关配置,最后关联需要用到的pool到cache pool. 1.建立ssd bucket tree 这是新增ssd bucket(vrack)后的osd tree.其中os

Cache和命中率

Cache的工作原理 Cache的工作原理是基于程序访问的局部性. 对大量典型程序运行情况的分析结果表明,在一个较短的时间间隔内,由程序产生的地址往往集中在存储器逻辑地址空间的很小范围内.指令地址的分布本来就是连续的,再加上循环程序段和子程序段要重复执行多次.因此,对这些地址的访问就自然地具有时间上集中分布的倾向. 数据分布的这种集中倾向不如指令明显,但对数组的存储和访问以及工作单元的选择都可以使存储器地址相对集中.这种对局部范围的存储器地址频繁访问,而对此范围以外的地址则访问甚少的现象,就称为

E3-1260L (8M Cache, 2.40 GHz) E3-1265L v2 (8M Cache, 2.50 GHz)

http://ark.intel.com/compare/52275,65728       Product Name Intel® Xeon® Processor E3-1260L (8M Cache, 2.40 GHz) Intel® Xeon® Processor E3-1265L v2 (8M Cache, 2.50 GHz) Code Name Sandy Bridge Ivy Bridge Essentials Status End of Life Launched Launch D

jfinal-ext shiro插件中cache无用

1.在项目中使用后,发现jfinal-ext shiro插件中cache配置无用 即,不管是否配置 <cache name="myRealm.authorizationCache" maxElementsInMemory="10000" overflowToDisk="true" eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="

MySQL源码之Thread cache

MySQL server为每一个connection建立一个thread为其服务,虽然thread create比着fork process代价高,单高并发的情况下,也不可忽略. 所以增加了Thread cache,重载了exit方式,cache Thread到一个队列中,当有新的THD请求时,从cache中取出来进行重用. 下面是一个thread cache工作的流程图,会比较清晰一点: MySQL源码之Thread cache,码迷,mamicode.com

十一:Centralized Cache Management in HDFS 集中缓存管理

集中的HDFS缓存管理,该机制可以让用户缓存特定的hdfs路径,这些块缓存在堆外内存中.namenode指导datanode完成这个工作. Centralized cache management in HDFS has many significant advantages. Explicit pinning prevents frequently used data from being evicted from memory. This is particularly important