Linux -- 在多线程程序中避免False Sharing
1.什么是false sharing
在对称多处理器(SMP)系统中,每个处理器均有属于自己的本地高速缓存区。

如图,CPU0和CPU1有各自的本地高速缓存区(cache)。线程0和线程1会用到不同的变量,它们在内存中彼此相邻。内存以64字节分割高速缓存行,我们假设红色变量与蓝色变量恰好分配在同一条高速缓存行中。CPU如果想要读取变量,会以高速缓存行的形式加载到本地高速缓存区中。这个例子中,CPU0和CPU1加载了同一条高速缓存行。然后线程0修改了红色变量,线程1修改了蓝色变量,这导致了CPU1中红色变量不正常,CPU0中蓝色变量不正常,从而导致高速缓存行无效,并强制内存更新以维持高速缓存的一致性。
2.(intel)如何确保多个CPU中的高速缓存的数据一致性
Intel处理器遵循MESI协议(Modified/Exclusive/Shared/Invalid,修改/独占/共享/无效)。
独占:
首次加载高速缓存行时,处理器将高速缓存行标记为”独占”访问,一旦该高速缓存行被标记为独占,后续加载可以自由使用缓存中的现有数据。
共享:
如果该处理器看到相同的高速缓存行被其它处理器加载到总线上,就会将该高速缓存行标记为”共享”访问。
修改:
如果处理器修改并保存了”共享”的高速缓存行,该缓存行将被标记为”修改”,所有其它处理器会受到一条”无效”的信息。当处理器A看到其它处理器访问标记为”修改”的相同高速缓存,A会将该高速缓存行存回内存,并将其标记为”共享”,其它处理器丢失自己的对应的高速缓存行。
无效:
处理器之间频繁协调,将”修改”的高速缓存行写入内存,然后再加载
3.解决假共享的方法
所有方法的目的都是确保引起false sharing的变量在内存中存放的位置相隔足够远,从而不会驻留在同一个高速缓存行中。
方法1: 使用编译指令强制对齐单个变量。
使用__declspec (align(64))声明变量
例: 单个变量
__declspec (align(64)) int thread1_global_variable;
__declspec (align(64)) int thread2_global_variable;
例: struct
使用int padding[n]确保struct为64或64的倍数
struct ThreadParams
{
// For the following 4 variables: 4*4 = 16 bytes
unsigned long thread_id;
unsigned long v; // Frequent read/write access variable
unsigned long start;
unsigned long end;
// expand to 64 bytes to avoid false-sharing
// (4 unsigned long variables + 12 padding)*4 = 64
int padding[12];
};
__declspec (align(64)) struct ThreadParams Array[10];
方法2:使用数据的线程本地拷贝来减少false sharing的频率
struct ThreadParams
{
// For the following 4 variables: 4*4 = 16 bytes
unsigned long thread_id;
unsigned long v; //Frequent read/write access variable
unsigned long start;
unsigned long end;
};
threadFunc(void *parameter)
{
ThreadParams *p = (ThreadParams*) parameter;
// local copy for read/write access variable
unsigned long local_v = p->v;
for(local_v = p->start; local_v < p->end; local_v++)
{
// Functional computation
}
p->v = local_v; // Update shared data structure only once
}
假设v在这个循环中每一次循环都被修改,那么,每一次修改都将触发false sharing。因此,我们使用线程本地变量local_v,所有的中间修改都在本地完成,仅在p->v = local_v;时更新数据结构
原文见:https://software.intel.com/zh-cn/articles/avoiding-and-identifying-false-sharing-among-threads
Linux -- 在多线程程序中避免False Sharing的更多相关文章
- zz剖析为什么在多核多线程程序中要慎用volatile关键字?
[摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...
- 多线程程序中fork导致的一些问题
最近项目中,在使用多线程和多进程时,遇到了些问题. 问题描述:在多线程程序中fork出一个新进程,发现新的进程无法正常工作. 解决办法:将开线程的代码放在fork以后.也就是放在新的子进程中进行创建. ...
- Linux下多线程编程中信号量介绍及简单使用
在Linux中有两种方法用于处理线程同步:信号量和互斥量. 线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保 ...
- 为什么linux下多线程程序如此消耗虚拟内存【转】
转自:http://blog.csdn.net/chen19870707/article/details/43202679 权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 探 ...
- CountDownLatch在多线程程序中的应用
一.CountDownLatch介绍 CountDownLatch是JDK1.5之后引入的,存在于java.util.concurrent包下,能够使一个线程等待其他线程完成动作后再执行.构造方法: ...
- linux下Java程序中插入DB中国的数据乱码问题
首先,插入到DB数据,在Linux在查询时,现场展示??. 再次,在windows连接到db上,查看的结果并非乱码. 改动Eclipse软件中的编码:如上图:windows菜单->prefere ...
- 如何在linux用户空间程序中打印时间戳?
1. 使用clock_gettime接口即可 2. clock_gettime的使用方法: 2.1 定义一个结构体 struct timespec ts; 2.2 调用clock_gettime获取当 ...
- Linux 多线程应用中如何编写安全的信号处理函数
http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...
- Linux 多线程应用中如何编写安全的信号处理函数【转】
转自:https://www.cnblogs.com/virusolf/p/4945642.html http://blog.163.com/he_junwei/blog/static/1979376 ...
随机推荐
- Eclipse修改项目jdk版本
修改项目jdk版本(@Override的解决方法) (1)Eclipse的Window-Preferences->Java->Compiler(2)Eclipse的Project-> ...
- 线性查找与二分查找(python)
# -*- coding: utf-8 -*- number_list = [0, 1, 2, 3, 4, 5, 6, 7] def linear_search(value, iterable): f ...
- 【HDU-1045,Fire Net-纯暴力简单DFS】
原题链接:点击! 大致题意:白块表示可以放置炮台的位置——每个炮台可以攻击到上下左右的直线上的炮台(也就是说在它的上下左右直线上不可以再放置炮台,避免引起互相攻击),黑块表示隔离墙的位置——不可放 ...
- react相关知识点总结
1 JSX解析的问题 JSX其实是语法糖: 开发环境会将JSX编译成JS代码 react定义的方法,用来解析html,第一个参数是“html元素”,第二个参数是“属性”,第三个参数是其子元素: 所以下 ...
- async/await中reject的问题
promise 返回的 resolve 对象可能用 await 去接,但是 reject 无法用 await 接收到,所以要用 try catch 去处理 例如发送邮件的接口设置: async fun ...
- 【转载】浅谈HTTPS以及Fiddler抓取HTTPS协议
最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...
- 使用UEditor 报错Cannot read property 'nodeType' of undefined 解决办法
报如下错误 解决办法: //对编辑器的操作最好在编辑器ready之后再做 ue.ready(function() { }) <!-- 实例化编辑器 --> <script type= ...
- 原生JS实现购物车全选多选按钮功能
对于JS初学者来说,一个完整的购物车实现还是挺难的,逻辑功能挺多.写出完整功能,能提升不少JS基础,下面实现购物车全选多选按钮功能: 首先HTML及CSS部分: <style> table ...
- VIM--保存和退出等命令
在 Linux 中使用 vim 时,输入 vim xxx.file 按 ESC,左下角就可以进行输入 :w 保存但不退出 :wq 保存并退出 :q 退出 :q! 强制退出,不保存 :e! 放弃所有修改 ...
- kindeditor如何使用
亲测能用: URL地址:https://jingyan.baidu.com/article/ab69b270b287332ca7189f19.html