上篇博客:http://blog.youkuaiyun.com/pennyliang/archive/2010/10/20/5953939.aspx提出了一段代码,并没有给出解释,本文接上文继续展开讨论。
该文有很多网友回复,比较集中的看法是CPU字节对齐,巧合的是有一个朋友用这个代码做了测试,发现对齐和不对齐的代码执行的速度是一样的,原因是他的笔记本安装的linux操作系统,而笔记本是单核的,所以就出现了这个状况,如果和CPU字节对齐,在单核的情况下怎么会速度一样呢?另外如果是CPU字节对齐,把线程去掉,替换成两个函数依次执行,也应该有效率的差异。
这是一种典型的FALSE SHARING问题,在SMP(对称多处理)的架构下常见的问题。SMP简单的说就是多个CPU核,共享一个内存和总线,L1 cache也叫芯片缓存,一般是私有的,即每个CPU核带一个,L2 cache可能是私有的也可能是部分共享的。
为了表明FALSE SHARE带来的影响,设计了这个简单的多线程程序,包含两个线程,他们分别做求和使用不同的变量,但由于cnt_1的地址和cnt_2的地址在同一条cache line中,实测环境中cnt_1的地址为0x600c00,cnt_2的地址为0x600c08,而cache line的大小为64个字节(cache line大小可以通过getconf LEVEL1_DCACHE_LINESIZE得到),这样就会发生FALSE SHARING问题。将两个变量在64字节对齐后,cnt_1的地址为0x600c40,cnt_2的地址为0x600c80,恰好错开在两条cache line上,源代码参加上篇博客。
FALSE SHARING问题在此前的博客也有详细讨论,可以参见:http://blog.youkuaiyun.com/pennyliang/archive/2010/07/27/5766541.aspx
最后,可能有读者会问,有谁会这么脑残写这样的代码,日常编码怎么会碰到这样的问题呢?我给大家说一个具体的场景,假如有一个lock-free的queues,里面包含了很多类型的queue,每个queue包含一个head和一个tail,这两个值分别被消费者和生产者之间竞争,因此如果不考虑false sharing问题,可能会造成低效代码。这样一个多线程共享的队列结构(多生产者,多消费者共享)用以下哪种结构更好呢?我不再公布答案,有兴趣的朋友可以去找找这方面的代码,看看他们是怎么写的。
【1】
struct queues{
type head1
type head2
...
type headn
type tail1
type tail2
...
type tailn
}
【2】
struct queue{
type head1
type tail1
type head2
type tail2
...
type headn
type tailn
}
【3】
struct queue{
type head1
type head2
...
type headn
type add_enough_padding;
type tail1
type tail2
...
type tailn
type add_enough_padding;
}
【4】
struct queue{
type head1
type add_enough_padding;
type tail1
type add_enough_padding;
type head2
type add_enough_padding;
type tail2
type add_enough_padding;
...
type headn
type add_enough_padding;
type tailn
type add_enough_padding;
}
本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/pennyliang/archive/2010/10/26/5966433.aspx