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的更多相关文章

  1. zz剖析为什么在多核多线程程序中要慎用volatile关键字?

    [摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...

  2. 多线程程序中fork导致的一些问题

    最近项目中,在使用多线程和多进程时,遇到了些问题. 问题描述:在多线程程序中fork出一个新进程,发现新的进程无法正常工作. 解决办法:将开线程的代码放在fork以后.也就是放在新的子进程中进行创建. ...

  3. Linux下多线程编程中信号量介绍及简单使用

    在Linux中有两种方法用于处理线程同步:信号量和互斥量. 线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保 ...

  4. 为什么linux下多线程程序如此消耗虚拟内存【转】

    转自:http://blog.csdn.net/chen19870707/article/details/43202679 权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 探 ...

  5. CountDownLatch在多线程程序中的应用

    一.CountDownLatch介绍 CountDownLatch是JDK1.5之后引入的,存在于java.util.concurrent包下,能够使一个线程等待其他线程完成动作后再执行.构造方法: ...

  6. linux下Java程序中插入DB中国的数据乱码问题

    首先,插入到DB数据,在Linux在查询时,现场展示??. 再次,在windows连接到db上,查看的结果并非乱码. 改动Eclipse软件中的编码:如上图:windows菜单->prefere ...

  7. 如何在linux用户空间程序中打印时间戳?

    1. 使用clock_gettime接口即可 2. clock_gettime的使用方法: 2.1 定义一个结构体 struct timespec ts; 2.2 调用clock_gettime获取当 ...

  8. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

  9. Linux 多线程应用中如何编写安全的信号处理函数【转】

    转自:https://www.cnblogs.com/virusolf/p/4945642.html http://blog.163.com/he_junwei/blog/static/1979376 ...

随机推荐

  1. PWA相关代码

    sw.js 文件 let CacheName = 'plus-v1'; var filesToCache = [ ]; self.addEventListener('install', functio ...

  2. java TCP 通信:服务端与客服端

    1.首先先来看下基于TCP协议Socket服务端和客户端的通信模型: Socket通信步骤:(简单分为4步) 1.建立服务端ServerSocket和客户端Socket 2.打开连接到Socket的输 ...

  3. 理解*arg 、**kwargs

    这两个是python中的可变参数.*args表示任何多个无名参数,它是一个tuple(元祖):**kwargs表示关键字参数,它是一个dict(字典).并且同时使用*args和**kwargs时,必须 ...

  4. TDOA基站 之 时间同步

    TDOA 和 TWR相比,标签可以用最少的信息来定位,但是对于基站要求很高,需要“时间同步”. 这也是TDOA算法的核心部分,很多套件对此讳莫如深,希望能沟通过本文使读者能对TODA同步有一定初步了解 ...

  5. [GraphQL] Query Lists of Multiple Types using a Union in GraphQL

    Unions are used when we want a GraphQL field or list to handle multiple types of data. With a Union ...

  6. 使用webuploader实现分片上传

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  7. .pro文件中设置版本等信息

    VERSION = 1.2.3 QMAKE_TARGET_PRODUCT = 产品名称QMAKE_TARGET_COMPANY = 公司QMAKE_TARGET_DESCRIPTION = 文件描述Q ...

  8. leetcode解题报告(14):Max Consecutive Ones

    描述 Given a binary array, find the maximum number of consecutive 1s in this array. Example 1: Input: ...

  9. 2017.11.8 Noip2017 考前模拟赛

    ----------------------------------T1---------------------------------- ——>足球联赛 题目描述 巴蜀中学新一季的足球联赛开 ...

  10. linux系列(十六):which命令

    1.命令格式: which 可执行文件名称 2.命令功能: which指令会在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果. 3.命令参数: -n 指定文件名长度,指定的长 ...