高速缓存提供的空间局部性是指虚拟内存,物理内存还是两者?

时间:2018-10-23 17:56:03

标签: c caching malloc virtual-memory

我试图理解为什么可以以某种方式编写使用数组的程序(例如矩阵乘法)来利用缓存的空间局部性。

  • 由高速缓存提供的空间局部性是指虚拟内存,物理内存还是两者之间的局部性? 当计算机系统将数据块从主内存带到CPU缓存时,它是否将虚拟或物理上连续的数据对象带入CPU缓存?

  • 当我们以非动态或动态方式(通过malloc())定义结构的数组或对象时,这样的数组或对象连续分配是正确的吗? “连续”是指虚拟内存还是物理内存,或者两者都是?

如果缓存的空间局部性是针对物理内存,而不一定是虚拟内存,并且OS可以分配给C程序,实际上不一定是物理上连续的数组,那么我们如何编写程序以利用缓存的空间局部性呢?

谢谢。

2 个答案:

答案 0 :(得分:2)

1)两者都是,但是为什么很微妙。

2)高速缓存对称为行的数据块进行操作,并且行中的字节在虚拟和物理上都是连续的。典型的行大小是16,32,64字节。 如果两个相邻的高速缓存行位于同一页内,则它们在物理上必须是连续的。典型的页面大小为4,8,16K。因此,具有32字节缓存行和4K基本页面的计算机每页有128行。

3,4)在结构的C成员中,并集或数组实际上是连续的。操作系统是否在物理上是连续的。

(1)第2部分:还有另一个称为转换后备缓冲区(TLB)的缓存,该缓存保留了最近使用的页面映射。如果没有这种机制,每个内存引用将需要两个物理内存引用:一个用于加载内存地址转换,然后将其应用于生成所需的内存引用。

假设您的TLB有32个条目(如今这真是太小了),并且您的代码沿数组是这样的:

char *p;
for (p = array; p < array + 4096; p++) {
     char *q;
     for (q = p; q < p + 32 * 4096; q += 4096) {
           *q += 1;
     }
}

您将有效地模拟一台没有TLB的机器,因为每个内存引用“ * q”在TLB中都会丢失,需要从内存中获取。

如果您知道缓存关联性和大小的详细信息,则可以为内存缓存构造类似的病理情况。或者,如果您不走运,您可能会不小心碰到它,并想知道为什么程序这么慢。

答案 1 :(得分:1)

假定您使用的编程语言仅支持一维数组,假设您有一个3x3矩阵。您可以通过实现

来实现二维数组
a [i, j] = a (i*3 + j)

如果您构建阵列访问权限。如果您遍历数组的元素,则如果您的外循环索引为i而内循环索引为j,则可以按以下顺序访问:

a(0), a(1), a(2), ..... a(8)

如果将j设为外循环索引,而将i设为内循环索引,则按顺序访问:

a(0), a(3), a(6), a(1), a(4), a(7), a(2), a(5), a(8)

您正在数组中跳来跳去。这种跳跃会对高速缓存造成破坏,因为高速缓存希望成组地获取内存。

具有多维数组的编程语言中仍然存在此问题。在这种情况下,编译器会为您将多个维度转换为一个维度。您遇到的问题是不同的编程语言对下标的排序方式有所不同。