Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
think-os-zh
提交
e38db311
T
think-os-zh
项目概览
OpenDocCN
/
think-os-zh
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
think-os-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
e38db311
编写于
7月 08, 2016
作者:
W
wizardforcel
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ch7.
上级
0d1b60e9
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
67 addition
and
0 deletion
+67
-0
ch7.md
ch7.md
+67
-0
未找到文件。
ch7.md
0 → 100644
浏览文件 @
e38db311
# 第七章 缓存
> 作者:[Allen B. Downey](http://greenteapress.com/wp/)
> 原文:[Chapter 7 Caching](http://greenteapress.com/thinkos/html/thinkos008.html)
> 译者:[飞龙](https://github.com/)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
## 7.1 程序如何运行
为了理解缓存,你需要理解计算机如何运行程序。你应该学习计算机体系结构来深入理解这个话题。这一章中我的目标是给出一个程序执行的简单模型。
当程序启动时,代码(或者程序文本)通常位于硬盘上。操作系统创建新的进程来运行程序,之后“加载器”将代码从储存器复制到主存中,并且通过调用
`main`
来启动程序。
在程序运行之中,它的大部分数据都储存在主存中,但是一些数据在寄存器中,它们是CPU上的小型储存单元。这些寄存器包括:
+
程序计数器(PC),它含有程序下一条指令(在内存中)的地址。
+
指令寄存器(IR),它含有当前执行的指令的机器码。
+
栈指针(SP),它含有当前函数栈帧的指针,其中包含函数参数和局部变量。
+
程序当前使用的存放数据的通用寄存器。
+
状态寄存器,或者位集训器,含有当前计算的信息。例如,位寄存器通常含有移位来存储上个操作是否是零的结果。
在程序运行之中,CPU执行下列步骤,叫做“指令周期”:
+
取指(Fetch):从内存中抓取下一条指令,储存在指令寄存器中。
+
译码(Decode):CPU的一部分叫做“控制单元”,将指令译码,并向CPU的其它部分发送信号。
+
执行(Execute):收到来自控制单元的信号后会执行合适的计算。
大多数计算机能够执行几百条不同的指令,叫做“指令集”。但是大多数指令可归为几个普遍的分类:
+
加载:将内存中的值送到寄存器。
+
算术/逻辑:从寄存器加载操作数,执行算术运算,并将结果储存到寄存器。
+
储存:将寄存器中的值送到内存。
+
跳转/分支:修改程序计数器,使控制流跳到程序的另一个位置。分支通常是有条件的,也就是说它会检查位寄存器中的旗标,只在设置时跳转。
一些指令集,包括普遍的x86,提供加载和算术运算的混合指令。
在每个指令周期中,指令从程序文本处读取。另外,普通程序中几乎一半的指令都用于储存或读取数据。计算机体系结构的一个基础问题,“内存瓶颈”就在这里。
在当前的台式机上,CPU通常为2GHz,也就是说每0.5ns就会初始化一条新的语句。但是它用于从内存中传送数据的时间约为10ns。如果CPU需要等10ns来抓取下一条指令,再等10ns来加载数据,它可能需要40个时钟周期来完成一条指令。
## 7.2 缓存性能
这一问题的解决方案,或者至少是一部分的解决方案,就是缓存。“缓存”是CPU上小型、快速的储存空间。在当前的计算机上,储存通常为1~2MiB,访问速度为1~2ns。
当CPU从内存中读取数据时,它将一份副本存到缓存中。如果再次读取相同的数据,CPU就直接读取缓存,不用再等待内存了。
当最后缓存满了的时候,为了能让新的数据进来,我们需要将一些数据扔掉。所以如果CPU加载数据之后,过了一段时间再来读取,数据就可能不在缓存中了。
许多程序的性能受限于缓存的效率。如果CPU所需的数据通常在缓存中,程序可以以CPU的全速来运行。如果CPU时常需要不在缓存中的数据,程序就会受限于内存的速度。
缓存的“命中率”
`h`
,是内存访问时,在缓存中找到数据的比例。“缺失率”
`m`
,是内存访问时需要访问内存的比例。如果
`Th`
是处理缓存命中的时间,
`Tm`
是缓存未命中的时间,每次内存访问的平均时间是:
```
h * Th + m * Tm
```
同样,我们可以定义“缺失惩罚”,它是处理缓存未命中所需的额外时间,
`Tp = Tm - Th`
,那么平均访问时间就是:
```
Th + m * Tp
```
当缺失率很低时平均访问时间趋近于
`Th`
,也就是说,程序可以表现为内存具有缓存的速度那样。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录