今天在看淘宝之前的一道面试题目,内容是

在高性能服务器的代码中经常会看到类似这样的代码:

typedef union
{
erts_smp_rwmtx_t rwmtx;
byte cache_line_align_[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_smp_rwmtx_t))];
}erts_meta_main_tab_lock_t;
erts_meta_main_tab_lock_t main_tab_lock[16];

请问其中用来填充的cache_line_align的作用是?

之前有学习到c语言中宏align是内存补齐的作用,那这个不就是cache line补齐?但是啥是cache line??为啥有这么一步?

1.首先,什么是cache line?

CPU处理指令时,由于“Locality of Reference”原因,需要决定哪些数据需要加载到CPU的缓存中,以及如何预加载。因为不同的处理器有不同的规范,导致这部分工作具有不确定性。在加载的过程中,涉及到一个非常关键的术语:cache line。

cache line是能被cache处理的内存chunks,chunk的大小即为cache line size,典型的大小为32,64及128 bytes. cache能处理的内存大小除以cache line size即为cache line。

了解了cache line,然后再熟悉一下cpu上cache的一些策略

2.cpu上cache的策略

cache entry (cache条目)
包含如下部分
1) cache line : 从主存一次copy的数据大小)
2) tag : 标记cache line对应的主存的地址
3) falg : 标记当前cache line是否invalid, 如果是数据cache, 还有是否dirty

cpu访问主存的规律
1) cpu从来都不直接访问主存, 都是通过cache间接访问主存
2) 每次需要访问主存时, 遍历一遍全部cache line, 查找主存的地址是否在某个cache line中.
3) 如果cache中没有找到, 则分配一个新的cache entry, 把主存的内存copy到cache line中, 再从cache line中读取.

cache中包含的cache entry条目有限, 所以, 必须有合适的cache淘汰策略
一般使用的是LRU策略.
将一些主存区域标记为non-cacheble, 可以提高cache命中率, 降低没用的cache

回写策略
cache中的数据更新后,需要回写到主存, 回写的时机有多种
1) 每次更新都回写. write-through cache
2) 更新后不回写,标记为dirty, 仅当cache entry被evict时才回写
3) 更新后, 把cache entry送如回写队列, 待队列收集到多个entry时批量回写.

cache一致性问题
有两种情况可能导致cache中的数据过期
1) DMA, 有其他设备直接更新主存的数据
2) SMP, 同一个cache line存在多个CPU各自的cache中. 其中一个CPU对其进行了更新.

3.为啥需要cache line 补齐呢?

让我们先看一个例子,

举例:

// 如下代码在SMP环境下存在cache频繁刷新问题
double sum=0.0, sum_local[NUM_THREADS];
#pragma omp parallel num_threads(NUM_THREADS)
{
int me = omp_get_thread_num();
sum_local[me] = 0.0; #pragma omp for
for (i = 0; i < N; i++)
sum_local[me] += x[i] * y[i]; #pragma omp atomic
sum += sum_local[me];
}
    因为sum_local数组是个全局变量, 多个线程都会访问, 并且, 各个线程访问的地方很接近, 会导致一个线程更新, 其他CPU的cache line失效.
    所以在尽量不要让更新频率非常高(例如,计数器)和经常访问的变量分布在同一个cache line中,以避免“cache ping-pong”,亦“false sharing”现象。
      OK,为啥需要补齐呢,上面的例子里面多个线程的访问会出现false sharing现象,如果服务器采用这样的,则服务器性能会严重影响,为了解决这个问题,最简单的办法是采用cache line 补齐的方法。
ps:在查找这个面试题的时候,有意思的是我在淘宝核心系统团队博客上发现了对这个题目的解答,我觉得简答的不是很认真,他们是参考一篇外文文献《Avoiding and Identifying False Sharing Among Threads》,这篇文章主要解决在SMP环境下cache line被频繁刷新的的问题。所以只是简单的将大意翻译过来。
将复制过来:

在做多线程程序的时候,为了避免使用锁,我们通常会采用这样的数据结构:根据线程的数目,安排一个数组, 每个线程一个项,互相不冲突. 从逻辑上看这样的设计无懈可击,但是实践的过程我们会发现这样并没有提高速度. 问题在于cpu的cache line. 我们在读主存的时候,数据同时被读到L1,L2中去,而且在L1中是以cache line(通常64)字节为单位的. 每个Core都有自己的L1,L2,所以每个线程在读取自己的项的时候, 也把别人的项读进去, 所以在更新的时候,为了保持数据的一致性, core之间cache要进行同步, 这个会导致严重的性能问题. 这就是所谓的False sharing问题, 有兴趣的同学可以wiki下.

解决方法很简单:
把每个项凑齐cache line的长度,实现隔离.

1
2
3
4
5
6
7
8
typedef
union
{
    
erts_smp_rwmtx_t rwmtx;
    
byte cache_line_align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
                
sizeof
(erts_smp_rwmtx_t))];
} erts_meta_main_tab_lock_t;
或者
_declspec (align(64))
int
thread1_global_variable;
__declspec
(align(64))
int
thread2_global_variable;

这就是为什么在高性能服务器中到处看到cache_line_align, 号称是避免cache的trash.

类似valgrind和intel vtune的工具可以做这个层次的性能微调.

(淘宝核心系统博客:
http://rdc.taobao.com/blog/cs/?p=523
 

由一道淘宝面试题到False sharing问题的更多相关文章

  1. Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform

    Expression构建DataTable to Entity 映射委托   1 namespace Echofool.Utility.Common { 2 using System; 3 using ...

  2. (转)从P1到P7——我在淘宝这7年

    (一) 2011-12-08 [原文链接] 今天有同事恭喜我,我才知道自己在淘宝已经七周年了.很多人第一句话就是七年痒不痒,老实说,也曾经痒过,但往往都是一痒而过,又投入到水深火热的工作中去.回家之后 ...

  3. 从P1到P7——我在淘宝这7年(转)

    作者: 赵超  发布时间: 2012-02-25 14:47  阅读: 114607 次  推荐: 153   [收藏] (一) 2011-12-08 [原文链接] 今天有同事恭喜我,我才知道自己在淘 ...

  4. 从P1到P7——我在淘宝这7年 - 子柳撰写

    http://kb.cnblogs.com/page/132752/来自博客园的整理版本,作者是子柳,博客地址:http://blog.sina.com.cn/calvinzhaoc (一) 2011 ...

  5. 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能

    前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...

  6. python推荐淘宝物美价廉商品

    完成的目标: 输入搜索的商品 以及 淘宝的已评价数目.店铺的商品描述(包括如实描述.服务态度.快递的5.0打分): 按要求,晒选出要求数量的结果,并按"物美价廉算法"排序后输出 思 ...

  7. ip地址库 新浪,淘宝

    原文连接地址:http://www.9958.pw/post/city_ip function getAddressFromIp($ip){ $urlTaobao = 'http://ip.taoba ...

  8. 仿淘宝分页按钮效果简单美观易使用的JS分页控件

    分页按钮思想:  1.少于9页,全部显示  2.大于9页,1.2页显示,中间页码当前页为中心,前后各留两个页码  附件中有完整例子的压缩包下载.已更新到最新版本  先看效果图:  01输入框焦点效果  ...

  9. php单点登录之模拟淘宝天猫同步登录

    说到单点登录大家都很了解,一个站点登录其他域会自动登录. 单点登录SSO(Single Sign On)的方法有很多,比如:p3p.共享session.共享cookice.第三方OAuth认证. 这里 ...

随机推荐

  1. 高级UIKit-02(文件操作)

    [day3_1_Sandbox]:沙箱的介绍 snadbox沙箱沙盒 沙箱根目录下的几个文件夹: 1.应用名称.app存放应用程序的素材 2.Documents:存放应用运行时需要用到的数据(关键性数 ...

  2. SuperSocket源码解析之启动过程

    一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...

  3. Mixtile LOFT

    日前,国内电子原型类开发团队Mixtile(深圳致趣科技)新推出的 Mixtile LOFT套件,受到业内著名的海外科技网站CNXSoft的关注和报道. 如果要阅读相关的原文报道,可点击这里.下面摘录 ...

  4. HDU 4336 Card Collector(动态规划-概率DP)

    Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful card ...

  5. 遗传算法Matlab源程序

    参考自: http://blog.163.com/zhaoshuyu_thomas/blog/static/461929072009103034816716/ 大家内容上可以参考上述文章,但其代码有很 ...

  6. OC-多线程安全隐患及一般解决办法

    1.多线程的安全隐患1.1>一块资源可能被多个线程共享,也就是多个线程可能会访问同一块资源,如多个线程访问同一个对象,变量,文件等当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题1. ...

  7. static在C和C++中的用法和区别

    static主要有三个作用: (1)局部静态变量 (2)外部静态变量/函数 (3)静态数据成员/成员函数 前两种C和C++都有,第三种仅在C++中有,下面分别作以下介绍: 一.局部静态变量 在C/C+ ...

  8. 基于visual Studio2013解决C语言竞赛题之1042字符串比较

          题目 解决代码及点评 /********************************************************************** ...

  9. POJ - 1422 Air Raid 二分图最大匹配

    题目大意:有n个点,m条单向线段.如今问要从几个点出发才干遍历到全部的点 解题思路:二分图最大匹配,仅仅要一条匹配,就表示两个点联通,两个点联通仅仅须要选取当中一个点就可以,所以有多少条匹配.就能够减 ...

  10. Storm流计算从入门到精通之技术篇(高并发策略、批处理事务、Trident精解、运维监控、企业场景)

    1.Storm全面.系统.深入讲解,采用最新的稳定版本Storm 0.9.0.1 :   2.注重实践,对较抽象难懂的技术点如Grouping策略.并发度及线程安全.批处理事务.DRPC.Storm ...