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

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

3天内不再提示

IT从业者应该知道的CPU Cache相关的知识

Linux阅码场 来源:cg 2019-01-04 09:30 次阅读

先来看一张本文所有概念的一个思维导图

为什么要有CPU Cache

随着工艺的提升最近几十年CPU的频率不断提升,而受制于制造工艺和成本限制,目前计算机的内存主要是DRAM并且在访问速度上没有质的突破。因此,CPU的处理速度和内存的访问速度差距越来越大,甚至可以达到上万倍。这种情况下传统的CPU通过FSB直连内存的方式显然就会因为内存访问的等待,导致计算资源大量闲置,降低CPU整体吞吐量。同时又由于内存数据访问的热点集中性,在CPU和内存之间用较为快速而成本较高的SDRAM做一层缓存,就显得性价比极高了。

为什么要有多级CPU Cache

随着科技发展,热点数据的体积越来越大,单纯的增加一级缓存大小的性价比已经很低了。因此,就慢慢出现了在一级缓存(L1 Cache)和内存之间又增加一层访问速度和成本都介于两者之间的二级缓存(L2 Cache)。下面是一段从What Every Programmer Should Know About Memory中摘录的解释:

Soon after the introduction of the cache the system got more complicated. The speed difference between the cache and the main memory increased again, to a point that another level of cache was added, bigger and slower than the first-level cache. Only increasing the size of the first-level cache was not an option for economical rea- sons.

此外,又由于程序指令和程序数据的行为和热点分布差异很大,因此L1 Cache也被划分成L1i (i for instruction)和L1d (d for data)两种专门用途的缓存。 下面一张图可以看出各级缓存之间的响应时间差距,以及内存到底有多慢!

什么是Cache Line

Cache Line可以简单的理解为CPU Cache中的最小缓存单位。目前主流的CPU Cache的Cache Line大小都是64Bytes。假设我们有一个512字节的一级缓存,那么按照64B的缓存单位大小来算,这个一级缓存所能存放的缓存个数就是512/64 = 8个。具体参见下图:

为了更好的了解Cache Line,我们还可以在自己的电脑上做下面这个有趣的实验。

下面这段C代码,会从命令行接收一个参数作为数组的大小创建一个数量为N的int数组。并依次循环的从这个数组中进行数组内容访问,循环10亿次。最终输出数组总大小和对应总执行时间。

#include "stdio.h" #include #include long timediff(clock_t t1, clock_t t2) { long elapsed; elapsed = ((double)t2 - t1) / CLOCKS_PER_SEC * 1000; return elapsed;}int main(int argc, char *argv[])#*******{ int array_size=atoi(argv[1]); int repeat_times = 1000000000; long array[array_size]; for(int i=0; i

如果我们把这些数据做成折线图后就会发现:总执行时间在数组大小超过64Bytes时有较为明显的拐点(当然,由于博主是在自己的Mac笔记本上测试的,会受到很多其他程序的干扰,因此会有波动)。原因是当数组小于64Bytes时数组极有可能落在一条Cache Line内,而一个元素的访问就会使得整条Cache Line被填充,因而值得后面的若干个元素受益于缓存带来的加速。而当数组大于64Bytes时,必然至少需要两条Cache Line,继而在循环访问时会出现两次Cache Line的填充,由于缓存填充的时间远高于数据访问的响应时间,因此多一次缓存填充对于总执行的影响会被放大,最终得到下图的结果:

gcc cache_line_size.c -o cache_line_size编译,并通过./cache_line_size执行。

了解Cache Line的概念对我们程序猿有什么帮助?我们来看下面这个C语言中常用的循环优化例子下面两段代码中,第一段代码在C语言中总是比第二段代码的执行速度要快。具体的原因相信你仔细阅读了Cache Line的介绍后就很容易理解了。

for(int i = 0; i < n; i++) {    for(int j = 0; j < n; j++) {        int num;            //code        arr[i][j] = num;    }}for(int i = 0; i < n; i++) {    for(int j = 0; j < n; j++) {        int num;            //code        arr[j][i] = num;    }}

CPU Cache 是如何存放数据的

你会怎么设计Cache的存放规则

我们先来尝试回答一下那么这个问题:

假设我们有一块4MB的区域用于缓存,每个缓存对象的唯一标识是它所在的物理内存地址。每个缓存对象大小是64Bytes,所有可以被缓存对象的大小总和(即物理内存总大小)为4GB。那么我们该如何设计这个缓存?

如果你和博主一样是一个大学没有好好学习基础/数字电路的人的话,会觉得最靠谱的的一种方式就是:Hash表。把Cache设计成一个Hash数组。内存地址的Hash值作为数组的Index,缓存对象的值作为数组的Value。每次存取时,都把地址做一次Hash然后找到Cache中对应的位置操作即可。 这样的设计方式在高等语言中很常见,也显然很高效。因为Hash值得计算虽然耗时(10000个CPU Cycle左右),但是相比程序中其他操作(上百万的CPU Cycle)来说可以忽略不计。而对于CPU Cache来说,本来其设计目标就是在几十CPU Cycle内获取到数据。如果访问效率是百万Cycle这个等级的话,还不如到Memory直接获取数据。当然,更重要的原因是在硬件上要实现Memory Address Hash的功能在成本上是非常高的。

为什么Cache不能做成Fully Associative

Fully Associative 字面意思是全关联。在CPU Cache中的含义是:如果在一个Cache集内,任何一个内存地址的数据可以被缓存在任何一个Cache Line里,那么我们成这个cache是Fully Associative。从定义中我们可以得出这样的结论:给到一个内存地址,要知道他是否存在于Cache中,需要遍历所有Cache Line并比较缓存内容的内存地址。而Cache的本意就是为了在尽可能少得CPU Cycle内取到数据。那么想要设计一个快速的Fully Associative的Cache几乎是不可能的。

为什么Cache不能做成Direct Mapped

和Fully Associative完全相反,使用Direct Mapped模式的Cache给定一个内存地址,就唯一确定了一条Cache Line。设计复杂度低且速度快。那么为什么Cache不使用这种模式呢?让我们来想象这么一种情况:一个拥有1M L2 Cache的32位CPU,每条Cache Line的大小为64Bytes。那么整个L2Cache被划为了1M/64=16384条Cache Line。我们为每条Cache Line从0开始编上号。同时32位CPU所能管理的内存地址范围是2^32=4G,那么Direct Mapped模式下,内存也被划为4G/16384=256K的小份。也就是说每256K的内存地址共享一条Cache Line。但是,这种模式下每条Cache Line的使用率如果要做到接近100%,就需要操作系统对于内存的分配和访问在地址上也是近乎平均的。而与我们的意愿相反,为了减少内存碎片和实现便捷,操作系统更多的是连续集中的使用内存。这样会出现的情况就是0-1000号这样的低编号Cache Line由于内存经常被分配并使用,而16000号以上的Cache Line由于内存鲜有进程访问,几乎一直处于空闲状态。这种情况下,本来就宝贵的1M二级CPU缓存,使用率也许50%都无法达到。

什么是N-Way Set Associative

为了避免以上两种设计模式的缺陷,N-Way Set Associative缓存就出现了。他的原理是把一个缓存按照N个Cache Line作为一组(set),缓存按组划为等分。这样一个64位系统的内存地址在4MB二级缓存中就划成了三个部分(见下图),低位6个bit表示在Cache Line中的偏移量,中间12bit表示Cache组号(set index),剩余的高位46bit就是内存地址的唯一id。这样的设计相较前两种设计有以下两点好处:

给定一个内存地址可以唯一对应一个set,对于set中只需遍历16个元素就可以确定对象是否在缓存中(Full Associative中比较次数随内存大小线性增加)

每2^18(256K)*16(way)=4M的连续热点数据才会导致一个set内的conflict(Direct Mapped中512K的连续热点数据就会出现conflict)

什么N-Way Set Associative的Set段是从低位而不是高位开始的

下面是一段从How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses摘录的解释:

The vast majority of accesses are close together, so moving the set index bits upwards would cause more conflict misses. You might be able to get away with a hash function that isn’t simply the least significant bits, but most proposed schemes hurt about as much as they help while adding extra complexity.

由于内存的访问通常是大片连续的,或者是因为在同一程序中而导致地址接近的(即这些内存地址的高位都是一样的)。所以如果把内存地址的高位作为set index的话,那么短时间的大量内存访问都会因为set index相同而落在同一个set index中,从而导致cache conflicts使得L2, L3 Cache的命中率低下,影响程序的整体执行效率。

了解N-Way Set Associative的存储模式对我们有什么帮助

了解N-Way Set的概念后,我们不难得出以下结论:2^(6Bits + 12Bits )=2^18=256K。即在连续的内存地址中每256K都会出现一个处于同一个Cache Set中的缓存对象。也就是说这些对象都会争抢一个仅有16个空位的缓存池(16-Way Set)。而如果我们在程序中又使用了所谓优化神器的“内存对齐”的时候,这种争抢就会越发增多。效率上的损失也会变得非常明显。具体的实际测试我们可以参考:How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses一文。 这里我们引用一张Gallery of Processor Cache Effects中的测试结果图,来解释下内存对齐在极端情况下带来的性能损失。

该图实际上是我们上文中第一个测试的一个变种。纵轴表示了测试对象数组的大小。横轴表示了每次数组元素访问之间的index间隔。而图中的颜色表示了响应时间的长短,蓝色越明显的部分表示响应时间越长。从这个图我们可以得到很多结论。当然这里我们只对内存带来的性能损失感兴趣。有兴趣的读者也可以阅读原文分析理解其他从图中可以得到的结论。

从图中我们不难看出图中每1024个步进,即每1024*4即4096Bytes,都有一条特别明显的蓝色竖线。也就是说,只要我们按照4K的步进去访问内存(内存根据4K对齐),无论热点数据多大它的实际效率都是非常低的!按照我们上文的分析,如果4KB的内存对齐,那么一个240MB的数组就含有61440个可以被访问到的数组元素;而对于一个每256K就会有set冲突的16Way二级缓存,总共有256K/4K=64个元素要去争抢16个空位,总共有61440/64=960个这样的元素。那么缓存命中率只有1%,自然效率也就低了。

Cache淘汰策略

在文章的最后我们顺带提一下CPU Cache的淘汰策略。常见的淘汰策略主要有LRU和Random两种。通常意义下LRU对于Cache的命中率会比Random更好,所以CPU Cache的淘汰策略选择的是LRU。当然也有些实验显示在Cache Size较大的时候Random策略会有更高的命中率

总结

CPU Cache对于程序猿是透明的,所有的操作和策略都在CPU内部完成。但是,了解和理解CPU Cache的设计、工作原理有利于我们更好的利用CPU Cache,写出更多对CPU Cache友好的程序。

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

    关注

    68

    文章

    10860

    浏览量

    211726
  • IT
    IT
    +关注

    关注

    2

    文章

    864

    浏览量

    63513

原文标题:关于CPU Cache -- 程序猿需要知道的那些事

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    10个问题及答案保障LED从业者用电安全

    照明开关为何必须接在火线上?单相三孔插座如何安装才正确?为什么?塑料绝缘导线为什么严禁直接埋在墙内?本文从十个问题以及答案方面解析了LED从业者需要注意的用电安全。
    发表于 02-24 09:41 1016次阅读

    开关电源从业者必看资料——《开关电源常规测试项目》

    开关电源从业者必看资料——《开关电源常规测试项目》
    发表于 04-29 22:03

    电源从业者必看必会之变压器基础知识_制作流程_详解

    适合电源从业者的基础知识入门维修必看
    发表于 11-10 20:42

    电源从业者必知必会之12种开关电源拓扑及计算公式

    =oxh_wx3、【周启全老师】开关电源全集http://t.elecfans.com/topic/130.html?elecfans_trackid=oxh_wx 电源从业者必知必会12种开关电源拓扑及计算公式
    发表于 06-02 22:03

    开关电源从业者入门资料 开关电源结构和基本原理

    非常适合开关电源从业者入门的资料 开关电源结构和基本原理资料分享来自于网络资源
    发表于 09-05 21:42

    软件测试从业者需要具备哪些技能

    当神一样看待,但是必须得会熟练的使用。操作系统相关知识Windows、linux、uinx这些都必须会使用,而且不仅仅是简单的操作,一般的服务管理、注册表编辑、命令行操作都需要会!要知道如果下一个连
    发表于 07-16 16:22

    软件测试从业者需要具备哪些技能

    当神一样看待,但是必须得会熟练的使用。操作系统相关知识Windows、linux、uinx这些都必须会使用,而且不仅仅是简单的操作,一般的服务管理、注册表编辑、命令行操作都需要会!要知道如果下一个连
    发表于 11-23 10:00

    电池配组方案(电池修复从业者必读)

    电池配组方案(电池修复从业者必读)    很多朋友来问:为什么电池修复好,经过测试性能相当
    发表于 11-16 13:44 5081次阅读

    机器学习从业者工具使用方面大数据分析

    数据科学是个变化极快的领域,业内人员需要不断更新知识体系,才可以在业内保持一定地位,不被时代淘汰。Stack Overflow Q&A、Conferences 和 Podcasts 是已从业者经常使用的学习平台。
    的头像 发表于 12-04 16:34 4073次阅读
    机器学习<b class='flag-5'>从业者</b>工具使用方面大数据分析

    NVIDIA持续助力AI教育及研究从业者

    AI教育关乎未来发展。一直以来,NVIDIA都坚持与AI教育和研究从业者并肩前行,以促进AI威廉希尔官方网站 的普及,迎接AI驱动下的未来经济。
    的头像 发表于 09-12 14:09 3189次阅读

    已入冰点的通信行业 从业者该清醒清醒了

    伴随着营业收入出现拐点,通信行业已经跌入冰点。面对如此不利的经营形式,通信行业从业企业和从业者该醒醒了。
    的头像 发表于 07-12 17:04 2450次阅读

    作为一名人工智能从业者应该看到什么

    不断流向业界、常规架构算力进入瓶颈期的今天,作为一名从业者应该看到什么?他们是这样说的……   吴恩达分享了自己对人工智能在接下来一年中发展的三个愿望:   缩短概念证明与生产之间的差距。尽管搭建好的模型很重要,但很多人现在也意识到,
    的头像 发表于 01-07 14:06 1718次阅读

    ML从业者如何阅读研究论文

      数据科学专业的性质是非常实用和涉及的。这意味着,数据科学领域与人工智能密切相关,人工智能仍然是一个发展中的领域,因此,它的从业者必须具备学术思维。
    的头像 发表于 04-08 14:22 828次阅读
    ML<b class='flag-5'>从业者</b>如何阅读研究论文

    专访AI从业者关彦斌:面对AI,人们需要了解如何去驾驭那个时代!

    ,也涌现了一大批人工智能从业者。对于未来人工智能发展,不妨听听相关从业者关彦斌的看法。 很多人都预测 2023 年将是 AI 之年,2022 年图像生成工具以及聊天工具 ChatGPT 等消费者化是人工智能开始普及应用的标志,2
    的头像 发表于 02-10 11:25 2064次阅读

    作为IT从业者,为什么我推荐华为云ECS?

    作为一名IT从业者,我经常会被问到关于云计算的问题。在这里,我想分享一下我的看法,并向大家推荐华为云ECS。 首先,让我们来了解一下什么是弹性云服务器。弹性云服务器(Elastic Cloud
    的头像 发表于 06-24 00:26 746次阅读