为什么A [k] [i] [j]对于3D数组的空间局部性更好? (其中i,j,k是行,列,深度)CMU lecture 55min

c++ - 3D阵列的空间局部性?-LMLPHP

最佳答案

实际上,该示例是完全错误的。当等级0从0..M-1开始时,该循环正在迭代0..N-1。除非M==N,否则您将读取错误的元素。

目的是让您的循环通过操纵循环的顺序来迭代地访问内存中物理上相邻的位置。

每当您的程序读取一个值时,CPU就会从缓存控制器中请求它。如果不在缓存中,则从内存中检索该值及其附近的值并将其存储在缓存中。

然后,如果您读取下一个元素,则它通常应该已经在缓存中,因此不会有缓慢的往返于下一个缓存或主机RAM的往返。

如果循环遍历整个地方而不是利用空间局部性,那么您就有遭受更多高速缓存未命中的风险,这会使事情变慢。

简而言之:从缓存中获取内容的速度很快,从RAM中获取内容的速度很慢,对循环进行排序以使它们接触相邻的位置有助于使缓存保持满意状态。

在图形中,我们通常这样做:

int a[M*N*N];

for(int offset=0; offset < M*N*N; ++offset)
{
  //int y = offset / cols;
  //int x = offset % rows;
  sum += a[offset];
}


如果您需要一个X,Y元素,

 offset = Y * cols + X;
 int val = a[offset];


或3D

offset = Z*N*N + Y*N + X


要么

offset = Z * rows * cols + Y * cols + X;


...并跳过所有多维数组的无聊性。

就个人而言,我只是这样做:

int *p = &a[0][0][0]; // could probably just do int* p=a, but for clarity...

//... array gets populated somehow
for(int i=0;i<M*N*N;++i)
{
  sum += p[i];
}


...但假定该数组是规则的正方形数组,而不是指针数组或指针数组的数组。

关于c++ - 3D阵列的空间局部性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40692318/

10-09 03:16