当前位置: 首页 > news >正文

暑假读书笔记第三天

今日文章:

小林coding:CPU 缓存一致性

小林coding:CPU 是如何执行任务的?

目录

    • CPU 缓存一致性
      • 写直达(Write Through)
      • 写回(Write Back)
      • 多核心缓存一致性
    • CPU读写与调度问题
      • CPU Cache **伪共享(False Sharing)**导致缓存失效
      • 避免伪共享
      • 线程调度
        • 任务
        • 调度类种类
        • 完全公平调度(Completely Fair Scheduling)

其他:

往期打卡


CPU 缓存一致性

数据写入 Cache 之后,内存与 Cache 相对应的数据将会不同,需要将数据同步写回内存才能保证数据的一致性

下面介绍两种针对写入数据的方法:

写直达(Write Through)

写直达是保证Cache和内存数据一致最简单的方式,写入数据到Cache时,把数据同时写入内存和 Cache 中,如果是新数据直接写入内存

在这里插入图片描述

写回(Write Back)

写直达频繁访问内存影响性能,写回机制中,写操作新数据仅仅写入Cache,只在替换数据时判断脏数据并写回内存

特殊情况为写未命中,写回策略对于该情况并没有做无意义操作

  1. 为什么写回未命中需要从内存中先读取回来再访问而不是直接写cache ?

    因为需要保证整个 cache line 块和内存数据一致,毕竟写入一般不会刚好是 cache line 块长

  2. 为什么写回未命中不能直接写内存还得写入cache再等写回去?

    因为数据改写后一般有用,用到了还得读,而且可能还会多次修改,必要时再写回内存有助于减少内存访问次数

在这里插入图片描述

多核心缓存一致性

写直达只需要在修改内存时广播事件通知各核心即可,主要看写回策略

写回策略是替换时写回,要实现各核心数据一致性,需要做到两点:

  • 第一点,某个 CPU 核心里的 Cache 数据更新时,必须要传播到其他核心的 Cache,这个称为写传播(Write Propagation);
  • 第二点,某个 CPU 核心里对数据的操作顺序,必须在其他核心看起来顺序是一样的,需要做到隔离性,事务隔离级别一般为串行化(Transaction Serialization)。

在这里插入图片描述

写操作一定要互斥,所以需要互斥锁

事务四大隔离级别:

在这里插入图片描述

写传播和事务串行化的具体实现技术

  • 总线嗅探
    • 写传播最常见的实现方式是总线嗅探(*Bus Snooping*),也就是总线广播,CPU核心监听总线上的广播事件
  • MESI 协议,四种状态标记Cache Line
    • Modified,已修改,脏标记,更新未写回内存,和独占的区别是其他核心发起读取请求时要先写回内存(因为会丢失已修改状态,不写回内存数据就不一致了)
    • Exclusive,独占,不用多核同步,直接修改
    • Shared,共享,相同的数据在多个 CPU 核心的 Cache 里都有,先通过广播让其他核心中该Cache Line 块无效,再更新当前Cache Line块
    • Invalidated,已失效,Cache Block 里的数据已经失效了,不可以读取该状态的数据。

具体例子:

  1. 当 A 号 CPU 核心从内存读取变量 i 的值,数据被缓存在 A 号 CPU 核心自己的 Cache 里面,此时其他 CPU 核心的 Cache 没有缓存该数据,于是标记 Cache Line 状态为「独占」,此时其 Cache 中的数据与内存是一致的;
  2. 然后 B 号 CPU 核心也从内存读取了变量 i 的值,此时会发送消息给其他 CPU 核心,由于 A 号 CPU 核心已经缓存了该数据,所以会把数据返回给 B 号 CPU 核心。在这个时候, A 和 B 核心缓存了相同的数据,Cache Line 的状态就会变成「共享」,并且其 Cache 中的数据与内存也是一致的;
  3. 当 A 号 CPU 核心要修改 Cache 中 i 变量的值,发现数据对应的 Cache Line 的状态是共享状态,则要向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后 A 号 CPU 核心才更新 Cache 里面的数据,同时标记 Cache Line 为「已修改」状态,此时 Cache 中的数据就与内存不一致了。
  4. 如果 A 号 CPU 核心「继续」修改 Cache 中 i 变量的值,由于此时的 Cache Line 是「已修改」状态,因此不需要给其他 CPU 核心发送消息,直接更新数据即可。如果 A 号 CPU 核心的 Cache 里的 i 变量对应的 Cache Line 要被「替换」,发现 Cache Line 状态是「已修改」状态,就会在替换前先把数据同步到内存。

在这里插入图片描述

CPU读写与调度问题

CPU Cache **伪共享(False Sharing)**导致缓存失效

①. 假设 1 号核心绑定了线程 A,2 号核心绑定了线程 B,线程 A 只会读写变量 A线程 B 只会读写变量 B,但变量 A 和 变量 B 的数据位于同一块

在这里插入图片描述

②. 1 号核心读取变量 A,A 和 B 的数据都会被加载到 Cache,并将此 Cache Line 标记为「独占」状态。

在这里插入图片描述

③. 2 号核心开始从内存里读取变量 B,此时 1 号和 2 号核心的 Cache Line 状态变为「共享」状态。

在这里插入图片描述

④. 1 号核心修改变量 A,核心2Cache Line失效,核心A状态变为「已修改」状态

在这里插入图片描述

⑤. 之后如果A,B线程交替修改A、B变量,就会发生伪共享,每次修改都要写回内存,重新读取,Cache 并没有起到缓存的效果

多个线程同时读写同一个 Cache Line 的不同变量时,而导致 CPU Cache 失效的现象称为伪共享(False Sharing)。

避免伪共享

在 Linux 内核中存在 __cacheline_aligned_in_smp 宏定义,是用于解决伪共享的问题。

在这里插入图片描述

比如对于存在a、b两个变量的结构体,可以将 b 的地址设置为 Cache Line 对齐地址

在这里插入图片描述

Java 并发框架 Disruptor 使用「字节填充 + 继承」的方式,来避免伪共享的问题。

在这里插入图片描述

根据 JVM 对象继承关系中父类成员和子类成员,内存地址是连续排列布局的,因此 RingBufferPad 中的 7 个 long 类型数据作为 Cache Line 前置填充,而 RingBuffer 中的 7 个 long 类型数据则作为 Cache Line 后置填充,这 14 个 long 变量没有任何实际用途,更不会对它们进行读写操作。

经过前后填充,无论怎么加载RingBufferFields都不会和其他RingBufferFields加载到一个Cache,所以多线程间不会出现伪共享问题

一句话总结就是要保证独占占据的全部Cache Line

线程调度

任务

在 Linux 内核中,进程和线程都是用 task_struct 结构体表示的,区别在于线程的 task_struct 结构体里部分资源是共享了进程已创建的资源,比如内存地址空间、代码段、文件描述符等

没有创建线程的进程,是只有单个执行流,它被称为是主线程。如果想让进程处理更多的事情,可以创建多个线程分别去处理,但不管怎么样,它们对应到内核里都是 task_struct。

在这里插入图片描述

Linux 内核里的调度器,调度的对象就是 task_struct,文章中把这个数据结构称为任务。

在这里插入图片描述

任务有不同的优先级以及响应要求,优先级数值越小越优先,在 Linux 系统中主要分为两种:

  • 实时任务,对系统的响应时间要求高,优先级小于100算实时任务
  • 普通任务,响应时间没有很高的要求,优先级在100~139范围算普通任务

nice表示优先级的修正数值,它与优先级(priority)的关系是:

priority(new) = priority(old) + nice

nice 值是映射到 100~139,这个范围是提供给普通任务用的,因此 nice 值调整的是普通任务的优先级。

指定nice值启动任务

在这里插入图片描述

调整运行中任务的nice值

在这里插入图片描述

改变任务的优先级以及调度策略

在这里插入图片描述

调度类种类

在这里插入图片描述

Deadline 和 Realtime 这两个调度类,都是应用于实时任务的,这两个调度类的调度策略合起来共有这三种,它们的作用如下

  • SCHED_DEADLINE:是按照 deadline 进行调度的,距离当前时间点最近的 deadline 的任务会被优先调度;(执行最快要到期的任务)
  • SCHED_FIFO:同优先级先来先服务,高优先级抢占
  • SCHED_RR:同优先级时间片轮转,高优先级抢占

而 Fair 调度类是应用于普通任务,都是由 CFS 调度器管理的,分为两种调度策略:

  • SCHED_NORMAL:普通任务使用的调度策略;
  • SCHED_BATCH:后台任务的调度策略,不和终端进行交互,因此在不影响其他需要交互的任务,可以适当降低它的优先级。

每个 CPU 都有自己的运行队列(Run Queue, rq),队列中包含三种调度类的运行队列

调度类有优先级Deadline > Realtime > Fair

先从 dl_rq 里选择任务,然后从 rt_rq 里选择任务,最后从 cfs_rq 里选择任务。因此,实时任务总是会比普通任务优先被执行。

在这里插入图片描述

完全公平调度(Completely Fair Scheduling)

这个算法的理念是想让分配给每个任务的 CPU 时间是一样,于是它为每个任务安排一个虚拟运行时间 vruntime,如果一个任务在运行,其运行的越久,该任务的 vruntime 自然就会越大,而没有被运行的任务,vruntime 是不会变化的。

当然为了区分优先级,需要考虑权重值

内核中会有一个 nice 级别与权重值的转换表,nice 级别越低的权重值就越大

在这里插入图片描述

其中NICE_0_LOAD可以视为常量

往期打卡

暑假读书笔记第二天

暑假读书笔记第一天


文章转载自:
http://banger.zzgtdz.cn
http://ares.zzgtdz.cn
http://cangue.zzgtdz.cn
http://biauricular.zzgtdz.cn
http://antimicrobial.zzgtdz.cn
http://alist.zzgtdz.cn
http://bonapartism.zzgtdz.cn
http://barback.zzgtdz.cn
http://aoudad.zzgtdz.cn
http://boathook.zzgtdz.cn
http://acquittance.zzgtdz.cn
http://chinela.zzgtdz.cn
http://calzada.zzgtdz.cn
http://bootlick.zzgtdz.cn
http://asin.zzgtdz.cn
http://afterthought.zzgtdz.cn
http://acmesthesia.zzgtdz.cn
http://carcinogen.zzgtdz.cn
http://bovine.zzgtdz.cn
http://arrantly.zzgtdz.cn
http://abnormity.zzgtdz.cn
http://aeromagnetic.zzgtdz.cn
http://avp.zzgtdz.cn
http://aphicide.zzgtdz.cn
http://caecal.zzgtdz.cn
http://biennium.zzgtdz.cn
http://capotasto.zzgtdz.cn
http://basil.zzgtdz.cn
http://astrologic.zzgtdz.cn
http://aluminum.zzgtdz.cn
http://www.dtcms.com/a/269263.html

相关文章:

  • Linux信号处理全解析
  • Qt中的QProcess类
  • 【学习笔记】大数定理,频率与概率,均值与期望的区别
  • MySQL数据表设计 系统的营销功能 优惠券、客户使用优惠券的设计
  • 2025Q2大模型更新汇总(大语言模型篇)
  • Web后端开发-分层解耦
  • 【Java面试】如何保证接口的幂等性?
  • Day06_刷题niuke20250707
  • pythone相关内容一
  • Spring 如何干预 Bean 的生命周期?
  • 洛谷 P5788 【模板】单调栈
  • 龙旗科技社招校招入职测评25年北森笔试测评题库答题攻略
  • 人工智能-基础篇-22-什么是智能体Agent?(具备主动执行和调优的人工智能产物)
  • elementUI vue2 前端表格table数据导出(二)
  • 超光谱相机的原理和应用场景
  • Java后端技术博客汇总文档
  • C语言——编译与链接
  • Dash 代码API文档管理工具 Mac电脑
  • JVM基础01(从入门到八股-黑马篇)
  • 力扣网编程274题:H指数之普通解法(中等)
  • ExcelJS 完全指南:专业级Excel导出解决方案
  • Web前端——css样式(盒子模型)
  • R语言爬虫实战:如何爬取分页链接并批量保存
  • Docker 稳定运行与存储优化全攻略(含可视化指南)
  • 田间杂草分割实例
  • 【PTA数据结构 | C语言版】求数组与整数乘积的最大值
  • OpenWebUI(2)源码学习-后端retrieval检索模块
  • YMS系统开发2-EAP自动化SECS/GEM协议详解
  • python的瑜伽体验课预约系统
  • vue时间轴,antd时间轴,带卡片时间轴