栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

多线程循环的效率

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程循环的效率

第二个比第一个更好。简单的答案:第二个最小化错误共享

现代CPU不会将字节一一加载到缓存中。它在称为缓存行的批处理中读取一次。当两个线程试图修改同一高速缓存行上的不同变量时,一个线程必须在修改一个高速缓存后重新加载它。

什么时候会发生?

基本上,内存中附近的元素将位于同一缓存行中。因此,数组中的相邻元素将位于同一缓存行中,因为数组只是一块内存。并且foo1和foo2可能也位于同一缓存行中,因为它们在同一类中定义为紧密。

class Foo {private int foo1;private int foo2;}

虚假分享有多糟糕?

我从处理器缓存效果库中引用示例6

private static int[] s_counter = new int[1024];private void UpdateCounter(int position){    for (int j = 0; j < 100000000; j++)    {        s_counter[position] = s_counter[position] + 3;    }}

在我的四核计算机上,如果我从四个不同的线程中调用带有参数0、1、2、3的UpdateCounter,则需要4.3秒才能完成所有线程。另一方面,如果我使用参数16,32,48,64调用UpdateCounter,则该操作将在0.28秒内完成!

如何检测虚假共享?

Linux Perf可用于检测高速缓存未命中,因此可以帮助您分析此类问题。

请参考来自CPU Cache Effects和Linux Perf的分析,使用perf从上面几乎相同的代码示例中找出L1缓存未命中:

Performance counter stats for './cache_line_test 0 1 2 3':10,055,747 L1-dcache-load-misses     #    1.54% of all L1-dcache hits

[51.24%]

Performance counter stats for './cache_line_test 16 32 48 64':  36,992 L1-dcache-load-misses     #    0.01% of all L1-dcache hits   [50.51%]

此处显示,没有错误共享,L1缓存命中的总数将从10,055,747下降至36,992。而且性能开销不在这里,而是在加载L2,L3高速缓存,在错误共享之后加载内存的系列中。

行业中有一些好的做法吗?

LMAX Disruptor是一个高性能线程间消息传递库,它是Apache
Storm中
工作人员内部通信的默认消息传递系统
。基础数据结构是一个简单的环形缓冲区。但是为了使其快速,它使用了许多技巧来减少错误共享。

例如,它定义了超类RingBufferPad以在RingBuffer中的元素之间创建填充:

abstract class RingBufferPad{    protected long p1, p2, p3, p4, p5, p6, p7;}

同样,当它为缓冲区分配内存时,它会在缓冲区的前面和后面创建填充,以便不会受到相邻存储空间中数据的影响:

this.entries   = new Object[sequencer.getBufferSize() + 2 * BUFFER_PAD];

资源

您可能想更多地了解所有魔术。看看作者的其中一篇文章:剖析干扰者:为什么这么快



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/570020.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号