香港六合彩现金网 本文转载自微信公众号「小林coding」,作家小林coding 。转载本文请干系小林coding公众号。 公共好,我是小林。 周末的时候,有个读者跟我说,口试字节的时候被问到:「什么是伪分享?又该怎么幸免伪分享的问题?」 这个其实是锻练 CPU 缓存的问题,我之前的图解系统也有提到过。 今天,我再跟公共讲一下。 正文 CPU 如何读写数据的?先来意志 CPU 的架构,惟有贯通了 CPU 的 架构,能力更好地贯通 CPU 是如何读写数据的,关于当代 CPU 的架构图如下: ![]() 不错看到,一个 CPU 里正常会有多个 CPU 中枢,比如上图中的 1 号和 2 号 CPU 中枢,而且每个 CPU 中枢都有我方的 L1 Cache 和 L2 Cache,而 L1 Cache 正常分为 dCache(数据缓存) 和 iCache(提示缓存),L3 Cache 则是多个中枢分享的,这等于 CPU 典型的缓存端倪。 上头提到的都是 CPU 里面的 Cache,放眼外部的话,还会有内存和硬盘,这些存储建设共同组成了金字塔存储端倪。如下图所示: 皇冠博彩皇冠手机登录地址1从上图也不错看到,从上往下,存储建设的容量会越大,而看望速率会越慢。至于每个存储建设的看望延时,你不错看下图的表格: 你不错看到, CPU 看望 L1 Cache 速率比看望内存快 100 倍,这等于为什么 CPU 里会有 L1~L3 Cache 的原因,斟酌等于把 Cache 动作 CPU 与内存之间的缓存层,以减少对内存的看望频率。 CPU 从内存中读取数据到 Cache 的时候,并不是一个字节一个字节读取,而是一块一块的形势来读取数据的,这一块一块的数据被称为 CPU Line(缓存行),是以 CPU Line 是 CPU 从内存读取数据到 Cache 的单元。 至于 CPU Line 大小,在 Linux 系统不错用底下的形势巡视到,你不错看我奇迹器的 L1 Cache Line 大小是 64 字节,也就意味着 L1 Cache 一次载入数据的大小是 64 字节。 那么对数组的加载, CPU 就会加载数组里面连续的多个数据到 Cache 里,因此咱们应该按照物理内存地址漫衍的律例去看望元素,这么看望数组元素的时候,Cache 掷中率就会很高,于是就能减少从内存读取数据的频率, 从而可提高圭臬的性能。 可是,在咱们不使用数组,而是使用单独的变量的时候,则会有 Cache 伪分享的问题,Cache 伪分享问题上是一个性能杀手,咱们应该要侧目它。 接下来,就来望望 Cache 伪分享是什么?又如何幸免这个问题? 皇冠客服飞机:@seo3687目下假定有一个双中枢的 CPU,这两个 CPU 中枢并走时行着两个不同的线程,它们同期从内存中读取两个不同的数据,差别是类型为 long 的变量 A 和 B,这个两个数据的地址在物理内存上是连续的,若是 Cahce Line 的大小是 64 字节,而且变量 A 在 Cahce Line 的滥觞位置,那么这两个数据是位于吞并个 Cache Line 中,又因为 CPU Line 是 CPU 从内存读取数据到 Cache 的单元,是以这两个数据会被同期读入到了两个 CPU 中枢中各自 Cache 中。 咱们来想考一个问题,若是这两个不同中枢的线程差别修改不同的数据,比如 1 号 CPU 中枢的线程只修改了 变量 A,或 2 号 CPU 中枢的线程的线程只修改了变量 B,会发生什么呢? 分析伪分享的问题目下咱们都集保证多核缓存一致的 MESI 公约,来施展这一所有这个词这个词的经过,若是你还不知说念 MESI 公约,你不错看我这篇著述「10 张图翻开 CPU 缓存一致性的大门」。 ①. 最启动变量 A 和 B 都还不在 Cache 里面,假定 1 号中枢绑定了线程 A,2 号中枢绑定了线程 B,线程 A 只会读写变量 A,线程 B 只会读写变量 B。 ②. 1 号中枢读取变量 A,由于 CPU 从内存读取数据到 Cache 的单元是 Cache Line,也偶合变量 A 和 变量 B 的数据包摄于吞并个 Cache Line,是以 A 和 B 的数据都会被加载到 Cache,并将此 Cache Line 符号为「独占」情景。 ③. 接着,2 号中枢启动从内存里读取变量 B,相同的亦然读取 Cache Line 大小的数据到 Cache 中,此 Cache Line 中的数据也包含了变量 A 和 变量 B,此时 1 号和 2 号中枢的 Cache Line 情景变为「分享」情景。 ④. 1 号中枢需要修转换量 A,发现此 Cache Line 的情景是「分享」情景,是以先需要通过总线发送音信给 2 号中枢,奉告 2 号中枢把 Cache 中对应的 Cache Line 符号为「已失效」情景,然后 1 号中枢对应的 Cache Line 情景酿成「已修改」情景,皇冠入口而且修转换量 A。 ⑤. 之后,2 号中枢需要修转换量 B,此时 2 号中枢的 Cache 中对应的 Cache Line 是已失效情景,另外由于 1 号中枢的 Cache 也有此相易的数据,且情景为「已修改」情景,是以要先把 1 号中枢的 Cache 对应的 Cache Line 写回到内存,然后 2 号中枢再从内存读取 Cache Line 大小的数据到 Cache 中,终末把变量 B 修改到 2 号中枢的 Cache 中,并将情景符号为「已修改」情景。 开云三公是以,不错发现若是 1 号和 2 号 CPU 中枢这么握续瓜代的差别修转换量 A 和 B,就会叠加 ④ 和 ⑤ 这两个标准,Cache 并莫得起到缓存的服从,诚然变量 A 和 B 之间其实并莫得任何的关系,可是因为同期包摄于一个 Cache Line ,这个 Cache Line 中的纵情数据被修改后,都会互相影响,从而出现 ④ 和 ⑤ 这两个标准。 因此,这种因为多个线程同期读写吞并个 Cache Line 的不同变量时,而导致 CPU Cache 失效的欢娱称为伪分享(False Sharing)。 幸免伪分享的标准因此,关于多个线程分享的热门数据,即正常会修改的数据,应该幸免这些数据刚好在吞并个 Cache Line 中,不然就会出现为伪分享的问题。 接下来,望望在骨子技俩中是用什么形势来幸免伪分享的问题的。 博彩平台在线客服在 Linux 内核中存在 __cacheline_aligned_in_smp 宏界说,是用于经管伪分享的问题。 从上头的宏界说,咱们不错看到: 火牛体育下载 若是在多核(MP)系统里,该宏界说是 __cacheline_aligned,也等于 Cache Line 的大小; 而若是在单核系统里,该宏界说是空的;因此,针对在吞并个 Cache Line 中的分享的数据,若是在多核之间竞争比拟严重,为了防护伪分享欢娱的发生,不错接受上头的宏界说使得变量在 Cache Line 里是对都的。 举个例子,有底下这个结构体: 伟大结构体里的两个成员变量 a 和 b 在物理内存地址上是连续的,于是它们可能会位于吞并个 Cache Line 中,如下图: 是以,为了防护前边提到的 Cache 伪分享问题,咱们不错使用上头先容的宏界说,将 b 的地址设立为 Cache Line 对都地址,如下: 这么 a 和 b 变量就不会在吞并个 Cache Line 中了,如下图: 是以,幸免 Cache 伪分享骨子上是用空间换技艺的想想,糜费一部分 Cache 空间,从而换来性能的进步。 咱们再来看一个哄骗层面的侧目决策,有一个 Java 并发框架 Disruptor 使用「字节填充 + 袭取」的形势,来幸免伪分享的问题。 Disruptor 中有一个 RingBuffer 类会正常被多个线程使用,代码如下: 皇冠hg86a你可能会以为 RingBufferPad 类里 7 个 long 类型的名字很奇怪,但事实上,它们诚然看起来毫无作用,但却对性能的进步起到了至关垂危的作用。 咱们都知说念,CPU Cache 从内存读取数据的单元是 CPU Line,一般 64 位 CPU 的 CPU Line 的大小是 64 个字节,一个 long 类型的数据是 8 个字节,是以 CPU 一下会加载 8 个 long 类型的数据。 凭证 JVM 对象袭取关系中父类成员和子类成员,内存地址是连续陈设布局的,因此 RingBufferPad 中的 7 个 long 类型数据动作 Cache Line 前置填充,而 RingBuffer 中的 7 个 long 类型数据则动作 Cache Line 后置填充,这 14 个 long 变量莫得任何骨子用途,更不会对它们进行读写操作。 从视频显示,这次C罗的越位体毛级越位。利雅得胜利继续猛攻,第33分钟,特莱斯在禁区外选择远射皮球击中横梁弹出。上半场比赛,双方0-0战平。易边再战,第51分钟,C罗在禁区内转身完成射门被没收。第75分钟,马内在禁区被绊倒,裁判观看VAR后判罚点球,C罗主罚点球命中,利雅得胜利客场1-0领先巴格达警察。 另外,RingBufferFelds 里面界说的这些变量都是 final 修饰的,意味着第一次加载之后不会再修改, 又由于「前后」各填充了 7 个不会被读写的 long 类型变量,是以不论怎么加载 Cache Line,这所有这个词这个词 Cache Line 里都莫得会发生更新操作的数据,于是只消数据被频繁地读取看望,就当然没稀零据被换出 Cache 的可能,也因此不会产生伪分享的问题。
|