False sharing问题及其解决方法

来源:互联网 发布:responsebody返回json 编辑:程序博客网 时间:2024/06/07 07:01

转载:http://webcache.googleusercontent.com/search?hl=zh-CN&newwindow=1&safe=strict&gbv=2&q=cache:-kZ77hm9shsJ:http://blog.yufeng.info/archives/tag/align+typedef+union+align&ct=clnk

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

具体的参考文章: http://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads/

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

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的工具可以做这个层次的性能微调.