简单看懂为伪共享及优化方法

1 篇文章 0 订阅
1 篇文章 0 订阅

伪共享概念当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。

必须要知道:

CPU对内存的访问速度较低,若每次计算都需要从内存中取数据,会导致CPU取数据的时间远大于CPU用在计算上的时间,浪费大量性能和时间。所以在CPU和内存中间增加了过渡,即缓存(cache),计算机会将CPU可能会用到的数据提前放在缓存上。

现在计算机一般有三级缓存L1, L2, L3;L1空间最小-最靠近CPU-提取数据速度最快,L3空间最大-离CPU最远(离内存最近)-获取数据速度最慢(还是比内存快)。除此之外还有寄存器,更小,更近,更快,不过不在本文讨论范畴之内。

对于多核计算机而言,通常每个核心会拥有独立的L1, L2缓存;所有核心共享L3和内存。CPU和缓存交换数据的最小单位为缓存行(cache line),现在计算机缓存行大小一般为64Byte。

实际情况:

当一个核心的线程A要取内存中某数据时,这个数据通常小于缓存行大小64Byte,所以此数据a连带着其内存相邻的一些数据一起,凑够1个缓存行,才能放到L1中,以便CPU后续操作快速读取。若数据b在内存中与数据a相邻,那么数据b很可能随数据a一起被线程A读入A的L1缓存行中。

注意了,当另一个核心的线程B要读写内存中的某数据b时,此时线程B能从内存中获得数据b所在缓存行的拷贝至B核心的L1中。实际上B核心和A核心获取的缓存行相同,均为内存中带数据a和b的一段。

但当线程A操作结束,线程A更新了数据a,为了数据一致性,其他包含数据a的缓存行会失效B的L1缓存行也在其中。那么线程B就必须要到内存中重新读取该缓存行。

核心从内存中获取数据的时间 是 核心从L1缓存获取数据的时间 约 10-50倍。

---------------------------------------------------------------------------------------------------------------------------------

下面的内容总结自面试官:如何写出让 CPU 跑得更快的代码? - 知乎

---------------------------------------------------------------------------------------------------------------------------------

内存那么大,L1那么小,L1怎么能知道要取内存上哪个位置的数据呢?

内存被分为很多块,取数据时,CPU通过内存物理地址计算出内存块索引,将其映射到L1(通取模运算),这样会有多个内存块取模结果相同。为了找到这些内存块中的一块,这些内存块又被编号。然后CPU其实需要的是内存块中的一个字,也就是目标数据,用一个偏移量记录数据在内存块中的位置。最后用一个标志位表示此内存块中的数据是否有效(MIES协议)。这样,缓存行中的数据其实是:索引+编号+偏移量+标志位+数据。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

如何优化?

1、如果你的数据在内存上是顺序储存的,那么顺序访问效率比随机访问效率更高。因为CPU读取第一个数据时,后面的一些数据也会被读取到缓存行上,顺序访问会增加缓存命中概率。

2、分支预测引导。在if—else分支上,CPU并不知道应该取if还是else后面的指令执行,如果取错了就白取了。CPU可以进行分支预测,判断此次执行取if还是else的的可能性,提前取对应分支下的指令到指令缓冲,如果预测成功,就可以直接使用。现在CPU一般能较好地进行分支预测。也可以通过宏定义#likely / #unlikely告诉CPU取哪个分支的可能更大。

3、核心绑定。线程在CPU上仅占用一个时间片,时间片用完就睡了,等着下一个时间片再被唤醒,但不一定能够在原来的核心上运行。前面说过,不同核心不共用L1,换核心运行就意味着要重新到L3或者内存读取。linux下<shced.h>sched_setaffinity()函数可以做到。

伪共享概念当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。

解决办法,别让它们在一个cache line里面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值