很久以前,受“C 中的数值配方”的启发,我开始使用以下结构来存储矩阵(二维数组)。
double **allocate_matrix(int NumRows, int NumCol)
{
double **x;
int i;
x = (double **)malloc(NumRows * sizeof(double *));
for (i = 0; i < NumRows; ++i) x[i] = (double *)calloc(NumCol, sizeof(double));
return x;
}
double **x = allocate_matrix(1000,2000);
x[m][n] = ...;
但是最近注意到很多人实现矩阵如下
double *x = (double *)malloc(NumRows * NumCols * sizeof(double));
x[NumCol * m + n] = ...;
从局部性的角度来看,第二种方法似乎很完美,但可读性很差......所以我开始怀疑,我的第一种存储辅助数组或**double
指针的方法真的很糟糕,还是编译器最终会优化它,这样它会更还是在性能上不及第二种方法?我很怀疑,因为我认为在第一种方法中,在访问值时会进行两次跳转,x[m]
然后x[m][n]
每次 CPU 都有可能先加载x
数组,然后再加载x[m]
数组。
ps 不用担心额外的存储空间**double
,对于大型矩阵来说,这只是一小部分。
PPS 因为很多人不太了解我的问题,所以我会尝试重新塑造它:我是否理解正确,第一种方法是一种局部性地狱,当每次x[m][n]
访问时,第一个x
数组将被加载到 CPU 缓存中并然后x[m]
将加载数组,从而以与 RAM 通信的速度进行每次访问。还是我错了,从数据局部性的角度来看,第一种方法也可以?