逐行访问矩阵元素与列方式

时间:2011-01-17 17:46:40

标签: c arrays

给出矩阵A[i][j]。如果我们想要添加矩阵的元素,哪种方法更好,为什么?

  1. 专栏
  2. 行明智
  3. 从我的观点来看,行方式更好,因为数组表示元素存储在连续的内存位置,因此访问它们所花费的时间更少。但是因为在RAM中获取每个位置需要相同的时间,这是否重要?

3 个答案:

答案 0 :(得分:32)

利用Spatial Locality

在C中,矩阵存储在r ow-major order中。因此,如果您访问元素a[i][j],则对元素a[i][j+1]的访问可能会访问缓存。不会访问主内存。缓存比主内存快,因此访问模式很重要。

当然,必须考虑更多因素,例如写访问/读访问,写策略(直写,写回/写分配,无写分配),多级缓存等。但这似乎对这个问题有点过分了。

使用分析工具(例如cachegrind)获得一些乐趣,并亲自查看。

例如,考虑一个访问4MB矩阵的虚拟程序。查看每种访问模式的未命中率之间的差异。

列访问权限

$ cat col_major.c 
#include <stdio.h>

int main(){

    size_t i,j;

    const size_t dim = 1024 ;

    int matrix [dim][dim];

    for (i=0;i< dim; i++){
        for (j=0;j <dim;j++){
            matrix[j][i]= i*j;
        }
    }
    return 0;
}

$ valgrind --tool=cachegrind ./col_major 

==3228== D   refs:      10,548,665  (9,482,149 rd   + 1,066,516 wr)
==3228== D1  misses:     1,049,704  (      968 rd   + 1,048,736 wr)
==3228== L2d misses:     1,049,623  (      893 rd   + 1,048,730 wr)
==3228== D1  miss rate:        9.9% (      0.0%     +      98.3%  )
==3228== L2d miss rate:        9.9% (      0.0%     +      98.3%  )

行访问

$ cat row_major.c 
#include <stdio.h>

int main(){
    size_t i,j;
    const size_t dim = 1024 ;
    int matrix [dim][dim];

    for (i=0;i< dim; i++)
        for (j=0;j <dim;j++)
            matrix[i][j]= i*j;

    return 0;
}

$ valgrind --tool=cachegrind ./row_major 

==3524== D   refs:      10,548,665  (9,482,149 rd   + 1,066,516 wr)
==3524== D1  misses:        66,664  (      968 rd   +    65,696 wr)
==3524== L2d misses:        66,583  (      893 rd   +    65,690 wr)
==3524== D1  miss rate:        0.6% (      0.0%     +       6.1%  )
==3524== L2d miss rate:        0.6% (      0.0%     +       6.1%  )

答案 1 :(得分:2)

如果阵列很小,那就不重要了。如果它们很大,那么读取时间可能会受到影响。最大的问题是缓存。如果您不能指望将完整矩阵一次加载到缓存中,那么您希望最大限度地减少遇到的缓存未命中数,因为处理缓存未命中相对耗时。

如果数组真的很大,那么你可以通过引起更多的页面交换来获得更大的性能命中率。

答案 2 :(得分:0)

对于C,处理多维数组的最佳方法是:

int a[MAX_I][MAX_J];
for (i = 0; i < MAX_I; ++i) {
   for (j = 0; j < MAX_J; ++j) {
      /* process a[i][j] */
   }
}

原因是C语言将数组作为具有偏移量的指针处理,请参阅:The C Programming Language