文档内容简介:
这篇文章主要是探讨现在的 CPU 的 cache 和内存系统之间的关系。
目录:
[Part 1]
[Part 2]
文档内容:
[Part 1]
CPU 速度的进展,一直比内存的速度进展要来得快。在 IBM PC XT 的时代,CPU 和内存的速度是差不多的。不过,后来 CPU 的速度就愈来愈快。再加上 DRAM 需要 refresh 才能保存数据的特性,DRAM 很快就跟不上 CPU 的速度了。现在的 CPU 都利用了 pipeline 的方式,可以每个 cycle 都 issue 一个(甚至多个)指令,再加上现在的 CPU 频率也比内存的频率高,内存的速度可说是远远落在 CPU 之后了。
为了避免内存成为 CPU 速度的瓶颈,现在的 CPU 都有 cache 的设计,甚至还有多层的 cache。Cache 的原理,主要是利用到大部分的程序,在处理数据时,都有一定程度的区域性。所以,我们可以用一小块快速的内存,来暂存目前需要的数据。
例如,几乎所有的程序,大部分的执行时间是花在一些循环中。这些循环通常都不大,可能只占整个程序空间的百分之一。如果一个程序经常要执行这段程序数千、甚至数万次,那就可以把这一小段程序放在 cache 中,CPU 就不需要每次都到很慢的主存储器中读取这段程序了。很多一般用途的程序,在存取数据时,也有类似的特性。因此,cache 的帮助非常大。如果没有 cache 的话,我们就不需要这么快的 CPU 了,因为系统的速度会卡在内存的速度上面。
现在的 CPU 往往也有多层的 cache。例如,Intel 的 Pentium III 500Mhz CPU,有 32KB 的 L1 cache,和 512KB 的 L2 cache。其中,L1 cache 内建在 CPU 内部,速度非常快,而且它是 Harvard 式,即指令用的空间和数据用的空间是分开的。Pentium III 500Mhz CPU 的 L1 cache 是分成 16KB 的 I-cache 和 16KB 的 D-cache。而 L2 cache 则是在 CPU 外面,以 250Mhz 的速度运作。另外,它和 CPU 之间的 bus 也只有 64 bits 宽。L2 cache 通常就不会区分指令和数据的空间,也就是 unified cache。
Cache 对速度有什么影响呢?这可以由 latency 来表示。CPU 在从内存中读取数据(或程序)时,会需要等待一段时间,这段时间就是 latency,通常用 cycle 数表示。例如,一般来说,如果数据已经在 L1 cache 中,则 CPU 在读取数据时(这种情形称为 L1 cache hit),CPU 是不需要多等的。但是,如果数据不在 L1 cache 中(这种情形称为 L1 cache miss),则 CPU 就得到 L2 cache 去读取数据了。这种情形下,CPU 就需要等待一段时间。如果需要的数据也不在 L2 cache 中,也就是 L2 cache miss,那么 CPU 就得到主存储器中读取数据了(假设没有 L3 cache)。这时候,CPU 就得等待更长的时间。
另外,cache 存取数据时,通常是分成很多小单位,称为 cache line。例如,Pentium III 的 cache line 长度是 32 bytes。也就是说,如果 CPU 要读取内存地址 0x00123456 的一个 32 bits word(即 4 bytes),且 cache 中没有这个资料,则 cache 会将 0x00123440 ~ 0x0012345F 之间的 32 bytes 数据(即一整个 cache line 长度)都读入 cache 中。所以,当 CPU 读取连续的内存地址时,数据都已经读到 cache 中了。
我写了一个小程序,用来测试 cache 的行为。这个程序会连续读取一块内存地址,并量测平均读取时间。这个程序的执行结果如下:
测试平台:
- Pentium III 500Mhz, PC100 SDRAM, 440BX chipset
- Celeron 466Mhz, PC100 SDRAM, VIA Apollo Pro 133 chipset
程序的执行文件和原始码可在这里下载。