某些内存访问会比其他的更慢

发布时间 2024-01-05 10:27:35作者: deeplearnMs
为了进一步补偿主内存的缓慢速度,许多计算机中都有高速缓存cache memory,一种非
常接近处理器的快速的、临时的存储,来加快对那些使用最频繁的内存字的访问速度。一
些计算机没有高速缓存,其他一些计算机则有一层或多层高速缓存,其中每一层都比前一
层更小、更快和更昂贵。当一个执行单元要获取的字节已经被缓存时,无需访问主内存即
可立即获得这些字节。高速缓存的速度快多少呢?一种大致的估算经验是,高速缓存层次
中每一层的速度大约是它下面一层的 10 倍。在桌面级处理器中,通过一级高速缓存、二
级高速缓存、三级高速缓存、主内存和磁盘上的虚拟内存页访问内存的时间开销范围可以
跨越五个数量级。这就是专注于指令的时钟周期和其他“奥秘”经常会令人恼怒而且没有
效果的一个原因,高速缓存的状态会让指令的执行时间变得非常难以确定。
当执行单元需要获取不在高速缓存中的数据时,有一些当前处于高速缓存中的数据必须被
舍弃以换取足够的空余空间。通常,选择放弃的数据都是最近很少被使用的数据。这一点
与性能优化有着紧密的关系,因为这意味着访问那些被频繁地访问过的存储位置的速度会
比访问不那么频繁地被访问的存储位置更快。
读取一个不在高速缓存中的字节甚至会导致许多临近的字节也都被缓存起来(这也意味
着,许多当前被缓存的字节将会被舍弃)。这些临近的字节也就可以被高速访问了。对于
性能优化而言,这一点非常重要,因为这意味着平均而言,访问内存中相邻位置的字节要
比访问互相远隔的字节的速度更快。
C++ 而言,这表示一个包含循环处理的代码块的执行速度可能会更快。这是因为组成
循环处理的指令会被频繁地执行,而且互相紧挨着,因此更容易留在高速缓存中。一段包
含函数调用或是含有 if 语句导致执行发生跳转的代码则会执行得较慢,因为代码中各个
独立的部分不会那么频繁地被执行,也不是那么紧邻着。相比紧凑的循环,这样的代码在
高速缓存中会占用更多的空间。如果程序很大,而且缓存有限,那么一些代码必须从高速
缓存中舍弃以为其他代码腾出空间,当下一次需要这段代码时,访问速度会变慢。类似
地,访问包含连续地址的数据结构(如数组或矢量),要比访问包含通过指针链接的节点
的数据结构快,因为连续地址的数据所需的存储空间更少。访问包含通过指针链接的记录
的数据结构(例如链表或者树)可能会较慢,这是因为需要从主内存读取每个节点的数据
到新的缓存行中。