专栏首页大话存储大话Queue、Buffer、Cache

大话Queue、Buffer、Cache

这个问题似乎跨越了十几年甚至更长。而且跨越了IT领域后端前端,跨越了硬件和软件。

Queue

队列用于两个模块(或者硬件模块,或者软件模块)之间传递消息,一般采用FIFO(先进先出)方式。下文中会解释这些消息里都是什么。在芯片内部,两个硬件模块(或者是CPU+固件,或者直接是组合逻辑电路)之间通常采用寄存器~寄存器对连的方式来传递数据/信号,但是寄存器对连的话,每次只能往寄存器里放一条数据,如果两端步调不一致,你处理快我处理慢的话,自然就有需求形成一个队列,那就是排布多个寄存器形成一列,然后再加上用于记录这一列寄存器中数据保存到什么位置的队列指针寄存器。生产者将消息从队列尾部入队,更新写指针,消费者从队列头部读走消息,更新读指针。有限的队列槽位形成一个虚拟的环形,不断生产消费,当写指针追赶上读指针时,队列满,有专门寄存器的控制位记录这个状态,有些设计还会产生一个中断来通知生产者。

如果生产者和消费者各自处于不同时钟域,对寄存器的信号采样时刻点不同,会采到错误的值,此时需要使用异步FIFO。异步FIFO的关键是必须采用格雷码来编码队列指针,格雷码可以保证每次只翻转1bit,保证消费者读取指针时不会产生误判。关于同步异步FIFO、格雷码等更详细内容请见大话计算机第1章。

如果Queue容量较大,一般不采用寄存器来充当,因为寄存器成本太高,存储1bit需要几十个晶体管,寄存器是为了响应时钟下边沿将输入端数据瞬间锁定并输送到输出端的,内部逻辑比较复杂。而成本低一些,响应速度也可以做到一个时钟周期的另一种存储器则是SRAM。SRAM无法充当寄存器因为它不具备下沿锁定并输出的能力,无法用于组合逻辑之间的隔离。CPU内部的各级缓存其实都是SRAM,有些L4缓存甚至用DRAM。

芯片内两个模块之间到底在传些什么东西?举例来讲。Raid控制器是一个芯片,其内部有通用CPU+固件代码在运行总控逻辑,芯片内部后端有多个SAS通道控制器,固件控制着DMA控制器从Host端主存的队列(软队列,下文讲)中取回对应的指令包(由Raid卡驱动准备好,当然最终是app发起I/O调用,沿着bio、scsi协议栈一路下来,生成了i/o request,并通过queue_command()调用到Raid卡驱动注册的request_fn()回调函数,后者将这个request封装到一个大包中,包中同时还描述了该指令对应的数据所在的主存位置等信息),固件解析该指令包内容,提取出scsi指令,并通过芯片内部queue将指令入队,然后通知后端硬件模块处理该指令,假设该scsi指令是读指令,则通过队列下发给后端SAS通道控制器,后者封装sas帧并传送给硬盘执行,写回来的数据在被DMA到主存。

网卡、显卡同样是这种套路,网卡拿到的是以太网帧,显卡拿到的是drawcall指令包,FPGA也是这么玩,都一样。I/O套路详见请见大话计算机第7章。

其他硬件队列还有很多,比如CPU的取指令单元取回的指令就在一个FIFO队列中等待被译码执行。芯片内部可以说到处都是队列。

软件队列,那就必须位于SDRAM里,比如刚才说的,各种I/O设备的驱动初始化时一般都会初始化至少两个队列,一个用于下发I/O,一个用于接收I/O完成回执(由I/O设备亲自写入完成队列并中断)。在驱动里你会发现总有一个函数是类似init_queue、init_queuepair等名字的。底层基本上就是kmalloc之类分配一段连续的内核内存,并将队列基地址写入I/O设备相关寄存器中,让后者知道去哪找这个队列。每次下发I/O之后驱动将队列的写指针更新到I/O控制器的相关寄存器让后者知道host端准备了多少i/o了。

所以,队列,就是一个队列,如其名一样,这个没有什么歧义。FIFO队列,顺着来,也有不顺着来的,不过一般不那么用。关于队列还有很多高级内容,比如VOQ(virtual output queue)、Virtual Channel等Qos方面概念,就不展开讲了,这些在大话计算机中第1/6/7章都有场景和原理介绍。

关于队列的扩展阅读:

大话流水线1

大话流水线2

大话流水线3

Buffer

Buffer,缓冲,不要叫它缓存,就是缓冲。就像不要把Fibre Channel叫做光纤网络或者光网络一样,说出去丢人。以太网也可以用光纤,光网络是指OTN,有些名词不要乱用。

缓冲缓的什么冲?就是两个模块之间生产和消费速度不匹配,导致积压。Queue不就是干这个的么?没错,很多时候,Queue就是Buffer,Buffer就是Queue,Buffer可以认为是一个队列深度很高的队列,能容纳相当量的数据。缓冲里的内容将会在一定时间内迅速消耗掉,而不是长期呆在里面,否则就成了缓存了。

Cache

缓存本质上是一块存储器,追求速度的硬件中一般采用SRAM来充当,比如CPU的各级缓存。不追求速度的可以用DRAM来盛放,比如Raid卡上的SDRAM缓存。缓存可以兼顾缓冲的作用,数据往缓存里仍,也可以匹配两边处理速度的差异,那是当然。但是缓存还有另一个作用,就是提升命中率。假设有个i/o写入0号扇区,而0好扇区的数据此时正在缓存里还没有被写入硬盘,那么缓存中的0扇区数据将被替换为最新写下来的这份,并继续留在缓存里。如果是缓冲,则缓冲队列头部假设已经存在之前写过的0扇区数据,又写了一次的话,那么之前的数据不会被删掉,会继续写到硬盘,后来新写入的0扇区数据也会被再写入硬盘一次。或许有些buffer有高级功能,能够发现这种重复而剔除掉之前的写数据只保留最新的,但是最新的数据一定不会长久待在buffer赖着不走。而缓存最关键的区别就在于数据会赖着不走,为什么,因为可能马上会被访问到。

既然如此,缓存容量有限,让谁待在里面,谁不待在里面,就是个需要决策的问题,让频繁访问的数据待在缓存会提升命中率,缓存就是看命中率,为命中率而生。于是有各种缓存替换算法比如LRU等,各类替换算法,以及缓存更高级的知识比如多核心缓存一致性等详见大话计算机第6章。(冬瓜哥总结19个关于缓存的知识点,写成了19节,美其名曰 “缓存19式”)。

有人说,“写buffer,读cache”,意思是指生产者将数据写到哪里?一般是写到buffer里,消费者从哪里读数据?一般是从cache读,也就是说buffer用于写加速,而cache用于读加速。这个说法并不准确,buffer一样用于读加速,经典的比如CPU内部的取指令缓冲,取指令单元从下层cache中取回若干条指令放到这个缓冲FIFO队列中,用于译码单元载入,这就是一段缓冲,但是确是用于读加速的,因为直接从cache中读还是不方便,速度也慢,做不到一个周期就载入指令,目前L1缓存起码也得经过两三个周期才能把数据读上来。

那么再看看,cache一定就是加速读操作的么?那可不一定。CPU算出数值之后,store指令可以将其存回主存,这个数据其实是被存到了L1 cache中存放,这个过程是典型的写加速,当然这个数据也用于后续访问的读加速。

所以,buffer和cache的区别并不在于读还是写,而是看它的目的只是为了缓冲,匹配速率不一致,还是为了缓存,提升命中率。

解决了你的疑惑了么?解决了的话请赏一下。

本文分享自微信公众号 - 大话存储(dahuacunchu),作者:冬瓜哥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 冬瓜哥彪悍图解Cache组关联

    根据《大话计算机》内容你点我贴一贴中所述,冬瓜哥收集了 “大话存储” 和 ”大话计算机” 两个公众号中帖子下的留言如下(蓝色表示往期已回答,红色表示本期...

    冬瓜哥
  • 【转发赠书】冬瓜哥详解超线程

    《大话计算机——计算机系统底层架构原理极限剖析》一书之所以需要在9月份(原本预计8月,但是目前看来审稿过程异常缓慢)才出来,原因是本次出版社对稿件要求太过苛刻,...

    冬瓜哥
  • 强力科普一下PCIe/CXL(Compute Express Link)

    PCIe设备与CPU交互的流量有2种:控制流量,访存流量。其中控制流量又分为多种:配置信息读写,电源管理,中断传送等等。访存流量则是PCIe设备与Host交互的...

    冬瓜哥
  • 技术那么多,说出你常用的那些【持续更新】

    Java帮帮
  • 用个小技巧,趁你不备,rm -rf你的电脑

    大家回想一下,你是不是遇到过这种情况:有时候,你访问一个网站,它突然给你下载了一个东西。特别是当你用 Chrome 的时候,浏览器直接就自动给你下载到“下载”文...

    青南
  • 算法:优先队列-理论

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    营琪
  • css3动画从入门到精通

    什么是css3动画? 通过 CSS3,我们能够创建动画,这可以在许多网页中取代动画图片、Flash 动画以及 JavaScript。 CSS3带来了圆角,半透明...

    xiangzhihong
  • HTML5使用ApplicationCache

    在html5中使用application cache可以把一些静态资源保存在客户端的浏览器上面。这样可以提高访问的速度,甚至是离线应用。关于applicatio...

    kklldog
  • 使用大batch优化深度学习:训练BERT仅需76分钟 | ICLR 2020

    在海量数据集上训练大型深度神经网络,是非常具有挑战性的。最近,有许多研究均使用大batch随机优化方法来解决此问题。在该研究领域中,目前最杰出的算法是LARS,...

    AI科技大本营
  • 搜狗财报:Q1亏损扩大、AI打响突围

    财报显示,搜狗一季度的总收入为2.573亿美元,同比增长2%,净亏损3160万美元。在此之前,彭博一致市场预期显示,搜狗Q1营收预计将达到2.51亿元美元,同比...

    刘旷

扫码关注云+社区

领取腾讯云代金券