0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CPU Cache伪共享问题

程序喵大人 来源:程序喵大人 作者:程序喵大人 2022-12-12 09:17 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

先看下这两段代码:

代码段1:

const int row = 10240;
const int col = 10240;
int matrix[row][col];
int TestRow() {
  //按行遍历
  int sum_row = 0;
  for (int r = 0; r < row; r++) {
    for (int c = 0; c < col; c++) {
      sum_row += matrix[r][c];
    }
  }
  return sum_row;
}

代码段2:

int TestCol() {
  //按列遍历
  int sum_col = 0;
  for (int c = 0; c < col; c++) {
    for (int r = 0; r < row; r++) {
      sum_col += matrix[r][c];
    }
  }
  return sum_col;
}

两段代码的目的相同,都是为了计算矩阵中所有元素的总和。

但有些区别:一个是按行遍历元素做计算,一个是按列遍历元素做计算。

它俩的运行速度有什么区别吗?

如图:

图中可以看到,行遍历的代码速度比列遍历的代码速度快很多。

为什么按行遍历的代码比按列遍历的代码速度快?这里就是CPU Cache在起作用。

什么是CPU Cache?

可以先看下这个存储器相关的金字塔图:

从下到上,空间虽然越来越小,但是处理速度越来越快,相应的,设备价格也越来越贵。

图中的寄存器和主存估计大家都知道,那中间的L1 、L2、L3是什么?它们起到了什么作用?

它们就是CPU 的Cache,如下图:

可以理解为CPU Cache就是CPU与主存之间的桥梁。

当CPU想要访问主存中的元素时,会先查看Cache中是否存在,如果存在(称为Cache Hit),直接从Cache中获取,如果不存在(称为Cache Miss),才会从主存中获取。Cache的处理速度比主存快得多。

所以,如果每次访问数据时,都能直接从Cache中获取,整个程序的性能肯定会更高。

那,如何提高CPU Cache的命中率?

但CPU Cache这里还有个小问题,看下这两段代码:

代码段1:

struct Point {
  std::atomic x;
  // char a[128];
  std::atomic y;
};
void Test() {
  Point point;
  std::thread t1(
      [](Point *point) {
        for (int i = 0; i < 100000000; ++i) {
          point->x += 1;
        }
      },
      &point);
  std::thread t2(
      [](Point *point) {
        for (int i = 0; i < 100000000; ++i) {
          point->y += 1;
        }
      },
      &point);
  t1.join();
  t2.join();
}

代码段2:

struct Point {
  std::atomic x;
  char a[128];
  std::atomic y;
};
void Test() {
  Point point;
  std::thread t1(
      [](Point *point) {
        for (int i = 0; i < 100000000; ++i) {
          point->x += 1;
        }
      },
      &point);
  std::thread t2(
      [](Point *point) {
        for (int i = 0; i < 100000000; ++i) {
          point->y += 1;
        }
      },
      &point);
  t1.join();
  t2.join();
}

两端代码的核心逻辑都是对Point结构体中的x和y不停+1。只有一点区别就是在中间塞了128字节的数组。

它们的执行速度却相差很大。

带128的比不带128的代码,执行速度快很多。

为什么?

看过我上面文章的同学应该就知道,每个CPU都有自己的L1和L2 Cache,而Cache line的大小一般是64字节,如果x和y之间没有128字节的填充,它俩就会在同一个Cache line上。

代码中开了两个线程,两个线程大概率会运行在不同的CPU上,每个CPU有自己的Cache。

当CPU1操作x时,会把y装载到Cache中,其他CPU对应的的Cache line失效。

然后CPU2加载y,会触发Cache Miss,它后面又把x装载到了自己的Cache中,其他CPU对应的Cache line失效。

然后CPU1操作x时,又触发Cache Miss。

它俩就会是大体这个流程:

频繁的触发Cache Miss,导致程序的性能相当差。

而如果x和y中间加了128字节的填充,x和y不在同一个Cache line上,不同CPU之前不会影响,它俩都会频繁的命中自己的Cache,整个程序性能就会很高,这就是传说中的False Sharing问题。

所以我们写代码时,可以基于此做深一层思考,如果我们写单线程程序,最好保证访问的数据能够相邻,在一个Cache line上,可以尽可能的命中Cache。

如果写多线程程序,最好保证访问的数据有间隔,让它们不在一个Cache line上,减少False Sharing的频率。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储器
    +关注

    关注

    39

    文章

    7714

    浏览量

    170848
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11216

    浏览量

    222930

原文标题:CPU Cache伪共享问题

文章出处:【微信号:程序喵大人,微信公众号:程序喵大人】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    gd32h737 开启cache程序跑飞是哪里的问题?

    gd32h737 在rtthread 4.1.1版本上运行,开启cache功能,程序跑飞,JLink连接失败的。错误信息没有。配置方式的说明吗? /*! briefenable the CPU
    发表于 09-11 08:28

    物联网设备识别与规避蜂窝移动网络基站的技术方案

    在蜂窝移动网络中,基站已成为物联网设备面临的重要安全威胁。基站通过模拟合法基站信号,利用更高的功率强制物联网设备连接,从而获取设备信息或进行恶意通信。随着物联网设备数量的快速增长,以及在关键
    的头像 发表于 09-02 16:55 700次阅读
    物联网设备识别与规避蜂窝移动网络<b class='flag-5'>伪</b>基站的技术方案

    真随机数和随机数的区别

    随机数在当前程序运行环境中是一种常用参数,目前主要分为两种,随机数和真随机数,本期我们就来讲一下二者的区别。
    的头像 发表于 08-27 17:46 1834次阅读

    高性能缓存设计:如何解决缓存共享问题

    在多核高并发场景下, 缓存共享(False Sharing) 是导致性能骤降的“隐形杀手”。当不同线程频繁修改同一缓存行(Cache Line)中的独立变量时,CPU缓存一致性协议会
    的头像 发表于 07-01 15:01 502次阅读
    高性能缓存设计:如何解决缓存<b class='flag-5'>伪</b><b class='flag-5'>共享</b>问题

    STM32H7的MPU配置与D-Cache冲突如何解决?​​

    现象​​: STM32H743 MPU 与 D-Cache 冲突问题详细描述** 硬件环境 MCU 型号 :STM32H743VIT6 开发板 :自定义板(或 STM32H743I-EVAL 等
    发表于 06-23 17:32

    如何在NXP MCU上启用D-Cache

    Data Cache,我已经能够减少其他 MCU 的推理时间。我想知道如何在 NXP MCU 上启用 D-Cache。任何其他性能提升策略也受到欢迎。
    发表于 03-27 07:48

    脑电迹系列之脑电迹处理与技术剖析

    在上一篇系列文章中了解到,脑电信号反映大脑神经元活动,在神经科学研究、临床诊断、脑机接口等领域应用广泛。但脑电信号幅值微弱极易受迹干扰。这些迹降低信号信噪比,增加数据变异性,导致实验结果偏差
    的头像 发表于 03-04 20:24 1921次阅读
    脑电<b class='flag-5'>伪</b>迹系列之脑电<b class='flag-5'>伪</b>迹处理与技术剖析

    脑电迹全解析:类型、成因与影响

    在脑电信号研究领域,脑电迹是影响数据准确性的关键因素。深入了解脑电迹,对获取可靠脑电数据、推动脑科学研究意义重大。脑电迹的产生根源脑电信号由大脑神经元电活动产生,极其微弱,通常处于几十微伏的低
    的头像 发表于 02-25 22:26 3102次阅读
    脑电<b class='flag-5'>伪</b>迹全解析:类型、成因与影响

    真双极和准双极,差动跟差动使用的性能有差别吗?

    最近需要用到差动输入的adc,找了很多型号,发现有真双极和准双极,差动输入方式的还分差动跟差动。网上找不到相关介绍,一般我们用单极adc要测量双极信号需要将信号抬高1/2vcc,我的理解是准双极的原理和抬高输入信号的原理一样。不知道真双极和准双极,差动跟差动使用的性
    发表于 02-08 07:52

    hyper-v共享,Hyper-V 共享:Hyper-V的资源共享设置

    的解决方案。今天就为大家介绍Hyper-V共享:Hyper-V的资源共享设置。    在Hyper-V虚拟化环境中,资源共享是实现高效管理和灵活部署的关键功能之一。Hyper-V提供了多种资源
    的头像 发表于 02-07 10:26 1832次阅读
    hyper-v<b class='flag-5'>共享</b>,Hyper-V <b class='flag-5'>共享</b>:Hyper-V的资源<b class='flag-5'>共享</b>设置

    高速缓冲存储器是内存还是外存,高速缓冲存储器是为了解决什么

    高速缓冲存储器(Cache)是内存的一种特殊形式,但它与通常所说的主存储器(RAM)有所不同。在计算机存储体系中,Cache位于CPU和主存储器之间,用于存储CPU近期访问过的数据或指
    的头像 发表于 01-29 11:48 3087次阅读

    有内部模式让ADS8363里面有两个AD,能一个AD工作在全差分,一个工作在差分吗?

    工作在差分吗? 我现在有两个信号需要同步采集,设计的是两个AD均工作在差分,但发现差分噪声较大,需要将其中一路调整为全差分,另一路电压范围不方便调节,所有希望仍然采用差分,采集
    发表于 01-02 07:57

    请问AD7616是单端输入还是差分输入?

    请问 AD7616是单端输入还是差分输入
    发表于 12-19 07:38

    什么是缓存(Cache)及其作用

    缓存(Cache)是一种高速存储器,用于临时存储数据,以便快速访问。在计算机系统中,缓存的作用是减少处理器访问主存储器(如随机存取存储器RAM)所需的时间。 缓存(Cache)概述 缓存是一种位于
    的头像 发表于 12-18 09:28 1.5w次阅读

    请问什么叫差分结构?什么叫真差分信号?

    请问什么叫差分结构?什么叫真差分信号?
    发表于 12-16 07:33