纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

C++性能榨汁机之伪共享 浅谈C++性能榨汁机之伪共享

lsgxeva   2021-06-09 我要评论
想了解浅谈C++性能榨汁机之伪共享的相关内容吗lsgxeva在本文为您仔细讲解C++性能榨汁机之伪共享的相关知识和一些Code实例欢迎阅读和指正我们先划重点:c++,伪共享下面大家一起来学习吧

前言

在多核并发编程中如果将互斥锁的争用比作“性能杀手”的话那么伪共享则相当于“性能刺客”“杀手”与“刺客”的区别在于杀手是可见的遇到杀手时我们可以选择战斗、逃跑、绕路、求饶等多种手段去应付但“刺客”却不同“刺客”永远隐藏在暗处伺机给你致命一击防不胜防具体到我们的并发编程中遇到锁争用影响并发性能情况时我们可以采取多种措施(如缩短临界区原子操作等等)去提高程序性能但是伪共享却是我们从所写代码中看不出任何蛛丝马迹的发现不了问题也就无法解决问题从而导致伪共享在“暗处”严重拖累程序的并发性能但我们却束手无策

缓存行

为了进行下面的讨论我们需要首先熟悉缓存行的概念学过操作系统课程存储结构这部分内容的同学应该对存储器层次结构的金字塔模型印象深刻金字塔从上往下代表存储介质的成本降低、容量变大从下往上则代表存取速度的提高位于金字塔模型最上层的是CPU中的寄存器其次是CPU缓存(L1L2L3)再往下是内存最底层是磁盘操作系统采用这种存储层次模型主要是为了解决CPU的高速与内存磁盘低速之间的矛盾CPU将最近使用的数据预先读取到Cache中下次再访问同样数据的时候可以直接从速度比较快的CPU缓存中读取避免从内存或磁盘读取拖慢整体速度

CPU缓存的最小单位就是缓存行缓存行大小依据架构不同有不同大小最常见的有64Byte和32ByteCPU缓存从内存取数据时以缓存行为单位进行每一次都取需要读取数据所在的整个缓存行即使相邻的数据没有被用到也会被缓存到CPU缓存中(这里又涉及到局部性原理后面文章会进行介绍)

缓存一致性

在单核CPU情况下上述方法可以正常工作可以确保缓存到CPU缓存中的数据永远是“干净”的因为不会有其他CPU去更改内存中的数据但是在多核CPU下情况就变得更加复杂一些多CPU中每个CPU都有自己的私有缓存(可能共享L3缓存)当一个CPU1对Cache中缓存数据进行操作时如果CPU2在此之前更改了该数据则CPU1中的数据就不再是“干净”的即应该是失效数据缓存一致性就是为了保证多CPU之间的缓存一致

Linux系统中采用MESI协议处理缓存一致性所谓MESI即是指CPU缓存的四种状态:

  • M(修改Modified):本地处理器已经修改缓存行即是脏行它的内容与内存中的内容不一样并且此 cache 只有本地一个拷贝(专有)
  • E(专有Exclusive):缓存行内容和内存中的一样而且其它处理器都没有这行数据
  • S(共享Shared):缓存行内容和内存中的一样, 有可能其它处理器也存在此缓存行的拷贝
  • I(无效Invalid):缓存行失效, 不能使用

每个CPU缓存行都在四个状态之间互相转换以此决定CPU缓存是否失效比如CPU1对一个缓存行执行了写入操作则此操作会导致其他CPU的该缓存行进入Invalid无效状态CPU需要使用该缓存行的时候需要从内存中重新读取由此就解决了多CPU之间的缓存一致性问题

伪共享

何谓伪共享?上面我们提过CPU的缓存是以缓存行为单位进行的即除了本身所需读写的数据之外还会缓存与该数据在同一缓存行的数据假设缓存行大小是32字节内存中有“abcdefgh”八个int型数据当CPU读取“d”这个数据时CPU会将“abcdefgh”八个int数据组成一个缓存行加入到CPU缓存中假设计算机有两个CPU:CPU1和CPU2CPU1只对“a”这个数据进行频繁读写CPU2只对“b”这个数据进行频繁读写按理说这两个CPU读写数据没有任何关联也就不会产生任何竞争不会有性能问题但是由于CPU缓存是以缓存行为单位进行存取的也是以缓存行为单位失效的即使CPU1只更改了缓存行中“a”数据也会导致CPU2中该缓存行完全失效同理CPU2对“b”的改动也会导致CPU1中该缓存行失效由此引发了该缓存行在两个CPU之间“乒乓”缓存行频繁失效最终导致程序性能下降这就是伪共享

如何避免伪共享

避免伪共享主要有以下两种方式:

1.缓存行填充(Padding):为了避免伪共享就需要将可能造成伪共享的多个变量处于不同的缓存行中可以采用在变量后面填充字节的方式达到该目的

2.使用某些语言或编译器中强制变量对齐将变量都对齐到缓存行大小避免伪共享发生

总结

一般伪共享都很隐蔽很难被发现当伪共享真正构成性能瓶颈的时候我们有必要去努力找到并解决它但是在大部分对性能追求没有那么高的应用中伪共享的存在对程序的危害很小有时并不值得耗费精力和额外的内存空间(缓存行填充)去查找系统存在的伪共享还是那句我一直以来遵循的话“不要过度优化不要提前优化”


相关文章

猜您喜欢

  • windows下C/C++的内存泄露检测 详解windows下C/C++的内存泄露检测

    想了解详解windows下C/C++的内存泄露检测的相关内容吗lsgxeva在本文为您仔细讲解windows下C/C++的内存泄露检测的相关知识和一些Code实例欢迎阅读和指正我们先划重点:c++,内存泄漏下面大家一起来学习吧..
  • Vue SpringBoot Shiro跨域 解决Vue+SpringBoot+Shiro跨域问题

    想了解解决Vue+SpringBoot+Shiro跨域问题的相关内容吗Java璐到底在本文为您仔细讲解Vue SpringBoot Shiro跨域的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Vue,SpringBoot,Shiro跨域,Vue,SpringBoot,Shiro下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式