【问题标题】:Spatial Locality for 3D array's?3D阵列的空间局部性?
【发布时间】:2017-04-03 04:53:50
【问题描述】:

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

【问题讨论】:

  • 比什么好????
  • 抱歉之前图片更新失败
  • 已经有一段时间了,但您能否编辑问题,将图像的相关部分添加为 text?更清楚地表明“i,j,k 是行、列、深度”是一个错误的假设。

标签: c++ c optimization memory-management multidimensional-array


【解决方案1】:

我认为是 OP 的问题

为什么 A[k][i][j] 更适合 3D 数组中的空间局部性? (其中 i,j,k 是行、列、深度)

来自对作为空间局部性示例给出的练习的误解,要求读者这样做

置换循环,使函数...具有良好的空间局部性

并且给出了这个代码:

int sum_array_3d(int a[M][N][N]) 
{
    int i, j, k, sum = 0;

    for (i = 0; i < M; i++)
        for (j = 0; j < N; j++)
            for (k = 0; k < N; k++)
                sum += a[k][i][j];

    return sum;
} 

我对这个任务的解释是要求学生要么将内部语句重写为sum += a[i][j][k];,要么改变循环的顺序:

int sum_array_3d(int a[M][N][N]) 
{
    int i, j, k, sum = 0;

    for (k = 0; k < M; k++)            // <-- those are reordered
        for (i = 0; i < N; i++)
            for (j = 0; j < N; j++)
                sum += a[k][i][j];     // <-- this is mantained, verbatim

    return sum;
}

【讨论】:

    【解决方案2】:

    实际上,这个例子是完全错误的。虽然等级 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];
    }
    

    ... 但假设该数组是一个常规方形数组,而不是指针数组或指针数组的数组。

    【讨论】:

      猜你喜欢
      • 2011-12-16
      • 2011-11-08
      • 2014-01-29
      • 1970-01-01
      • 2013-05-09
      • 2016-02-03
      • 1970-01-01
      • 2021-08-08
      • 2013-04-23
      相关资源
      最近更新 更多