内存管理:算法及其c/c++实现 翻译三

来源:互联网 发布:dis mac-add 编辑:程序博客网 时间:2024/05/01 06:10

内存层次结构

 

当一些人使用“内存”这个字眼时,他们一般指位于主板上专门用作数据存储的芯片。这些芯片提供的存储被称为随机访问存储器(Random Access Memory, RAM)、主存储器或者主存。在计算机发展的早期,当大型机大行其道时,存储器成为重要的部件。内存芯片提供的存储能力具有易失的特性,也就是说当关掉电源时,芯片里存储的数据也就丢失了。

 

有一些不同类型的RAMDRAMSDRAMSRAMVRAM DRAM (Dynamic RAM)在每一秒钟内必须为其充电几千次。SRAM (Static RAM)不需要像DRAM那样被刷新,它速度更快。不幸的是,SRAMDRAM更贵,不宜大量地使用。处理器的缓存一般使用SRAM。数量比较大的内存一般使用DRAM。最后,我们说说VRAM (Video RAM),它是由视频硬件使用的内存区域。下一章将给出一个怎样操作VRAM产生屏幕输出的例子。

 

最近技术的进步以及一些制造商使用特殊的优化技术导致出现了一些新的名词,在这我给出其中的一些:DDR SDRAMRDRAMESDRAM等等。DDR SDRAM表示双数据速率异步动态随机内存访(Double Data Rate Synchronous Dynamic Random Access Memory)RDRAMRambus DRAM的缩写,它是Rambus公司出品的高性能DRAM版本,它的数据传输率达到800MhzESDRAM代表增强的同步DRAM,它是Enhanced Memory Systems公司为了使用更加便宜的SDRAM替代SRAM而制造的。

 

一位是一个二进制数字(例如,一个10)。RAM芯片中的位是一个位元结构,它由晶体管或电容管(RAM的类型决定)所给的状态决定。每一个位元的数字可以相互转换。这些位元每8个分为一组,称为字节。字节是衡量存储设备内存数量的基本单元。在早期,硬件制造商使用不同的字节大小,有的制造商使用6位的字节,而另一个制造商可能使用16位的字节。然而,现在每一个人遵守的事实上的标准是8位的字节。

 

有一套基于字节的标准指定了内存区域的大小,它们是:

 

1 byte = 8 bits

1 word = 2 bytes

1 double word = 4 bytes

1 quad word = 8 bytes

1 octal word = 8 bytes

1 paragraph = 16 bytes

1 kilobyte (KB) = 1,024 bytes

1 megabyte (MB) = 1,024KB = 1,048,576 bytes

1 gigabyte (GB) = 1,024MB = 1,073,741,824 bytes

1 terabyte (TB) = 1,024GB = 1,099,511,627,776 bytes

1 petabyte (PB) = 1,024TB = 1,125,899,906,842,624 bytes

 

注释:20世纪80年代时,拥有兆级别的DRAM是一个很大的资产。当时的孩子们经常缠着他们的父母亲要买一个16KB的内存去更新他们的Atari400s,以便可以玩更大的游戏。那时,使用只有兆级别内存的计算机不会遇到什么问题,因为工程师只是使用汇编语言,并且编写的程序也比较小。事实上,我们经常引述Bill Gates1981年说的一句蹩脚的明言:“对每一个人来说,640K的内存应该足够了”。

 

现在,大多数作为开发的计算机至少拥有128MBDRAM内存。在2002年,256MB的内存似乎成为了标准。从现在开始十年以后,G级别的DRAM将成为标准(如果那时我们还使用DRAM的话)。真希望以后没有人引述我说的话! J

 

不是只有RAM才作为存储数据的地方,我们使用内存层次等级的概念。由于存储数据的地方不同,内存可以根据距离处理器的远近来排序,以下就是排序的结构:

1.       寄存器 (Registers)

2.       缓存 (Cache)

3.       内存 ( RAM )

4.       磁盘 (Disk storage)

在这些存储区域中,他们的主要区别就是内存延时(Memory Latency),也称为滞后时间。访问的存储越是靠近处理器,访问时间就越小。处理器访问磁盘的时间比访问在内存的时间要长得多。例如,DRAM延时是用纳秒来衡量,然而,磁盘访问延时是用毫秒来衡量。

 

 

 

Figure1-1

 

寄存器位于处理器内部,容量更小,处理器更加倾向于在寄存器中处理数据。大多数处理器日复一日的工作就是在寄存器中处理数据。

 

设计编译器的工程师将克服各种困难去把变量和常量放在寄存器中。大量的寄存器可以使更多的程序状态保存在处理器中,这样可以缩短处理器访问内存的时间。为了做到这一点,MIPS64型号的处理器设计了3264位的通用目的寄存器。Intel下一代64位的处理器安腾里面的寄存器更多,它实际上有几百个寄存器。

 

Intel Pentium 处理器有一个变化的寄存器数目,如下图,有616位的段寄存器,它们是:CSDSESFSGSSS,有832位的通用目的寄存器,它们是:EAXEBXECXEDXESIEDIEBPESP,有一个32位的错误标志寄存器EFLAGS,有一个32位的指令指针寄存器EIP

 

Figure1-2

 

 

还有4个系统寄存器:GDTRLDTRIDTRTR5个模式控制寄存器:CR0CR1CR2CR3CR4,这两类寄存器使内存管理更加便利。这些寄存器将在本章的后面部分介绍。

 

注释:注意到Pentium处理器的寄存器集合受到历史原因的制约是很有趣的。向后兼容的设计要求使得Pentium处理器比8086处理器多不了多少寄存器。

缓存提供了比访问DRAM更快的临时存储,把程序中密集计算的部分放入缓存能够避免处理器不断访问DRAM的开销,这样可以节省大量的时间。有几类不同类型的缓存。L1缓存位于处理器内部,L2缓存是位于处理器外面的SRAM,例如,Pentium 4 芯片有256KB512KBL2高级传输缓存。

 

注释:如果你要优化在缓存中执行的代码,你应该避免不必要的函数调用。对函数的调用要求处理器执行位于缓存外面的代码,这将引起缓存重新加载新的数据,这就是一些C编译器提供内联函数选项的原因,使用内联函数不好的地方是它比不使用内联函数的程序的体积要更大一些。尺寸和速度的权衡是整个计算机科学必须经常考虑的问题。

 

磁盘是我们最后利用的存储空间。一般来说,磁盘被用作创建虚拟内存。虚拟内存是用磁盘模拟内存的一种技术。换句话说,DRAM内存部分通常被写入磁盘中,这样可以使处理器访问的内存的数量比实际的物理内存数量要大。例如,如果你有10MBDRAM,并且你用2MB的磁盘空间去模拟内存,那么处理器实际能访问的虚拟内存为12MB

 

注释:我在本书中不断提到的一个观点是磁盘I/O花费很高。我以前也提到过,访问磁盘的延时是在毫秒级别,从处理器的角度来说,这个时间过于长了。这种情况类似与在达克他州定购一块比撒饼。如果你的冰箱里有冻好的比撒饼(就像访问内存里的数据),那就幸运了,不到30分钟你就可以加热它,如果你不够幸运,那么你就得打电话给卖比撒饼的人(就像访问磁盘上的数据一样),并且在送饼人经过 150英里的长途跋涉把饼送过来之前你得等上5个小时。

 

使用虚拟内存就像跟魔鬼打交道一样,的确,你将得到更多的额外内存,但是你将在性能上付出代价。磁盘I/O包括一系列必须进行的动作,其中一些是机械动作。据估计,Windows分页将占去执行时间的10%的时间。管理虚拟内存要求处理器做很多薄记工作。我将在后面介绍这些薄记工作的具体情况。

 

磁盘总是比RAM便宜得多,在1960年的那个年代,8KBRAM就是一个很大的投资,那时使用磁盘创建虚拟内存可能很有意义。然而,现在的DRAM和磁盘的价格相差不大。买一台拥有512MBSDRAM的计算机不是很难。这样,虚拟内存可能将成为历史,或者作为紧急保护时才用到。