[英]What is the convention of indexing 2D array with x/y coordinates in C?
我一直在编写小程序,我必须在板上使用坐标系统(x / y在2d数组中)并且考虑是否应该使用像array[x][y]
这样的索引,这对我来说更自然或者array[y][x]
这将更好地匹配数组在内存中的表示方式。 我相信如果我一致并且这只是命名问题,这两种方法都会起作用,但是在编写更大的程序时会有什么约定呢?
在我的领域(图像处理)中, [y][x]
惯例更常见。 无论你做什么,都要保持一致并记录好。
您还应该考虑要对这些数组做什么,以及这是否对时间至关重要。
如评论中所述:元素a[r][c+1]
紧邻a[r][c]
。 在迭代较大的数组时,这一事实可能会对性能产生相当大的影响。 正确的遍历顺序将导致高速缓存行被充分利用:当访问一个数组索引时,它被认为是“可能”,之后,将访问下一个索引,并将整个内存块加载到缓存。 如果您之后访问完全不同的内存位置(即下一行中的一个),则会浪费此缓存带宽。
如果可能,您应该尝试使用适合实际内存布局的遍历顺序。
(当然,这很大程度上是关于“约定”和“习惯”:当编写像a[row][col]
这样的数组访问时,这通常被解释为数组访问a[y][x]
,这是由于x轴是水平的,y轴是垂直的......)
这是一个小例子,演示了“错误”遍历顺序的潜在性能影响:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
float computeSumRowMajor(float **array, int rows, int cols)
{
float sum = 0;
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
sum += array[r][c];
}
}
return sum;
}
float computeSumColMajor(float **array, int rows, int cols)
{
float sum = 0;
for (int c=0; c<cols; c++)
{
for (int r=0; r<rows; r++)
{
sum += array[r][c];
}
}
return sum;
}
int main()
{
int rows = 5000;
int cols = 5000;
float **array = (float**)malloc(rows*sizeof(float*));
for (int r=0; r<rows; r++)
{
array[r] = (float*)malloc(cols*sizeof(float));
for (int c=0; c<cols; c++)
{
array[r][c] = 0.01f;
}
}
clock_t start, end;
start = clock();
float sumRowMajor = 0;
for (int i=0; i<10; i++)
{
sumRowMajor += computeSumRowMajor(array, rows, cols);
}
end = clock();
double timeRowMajor = ((double) (end - start)) / CLOCKS_PER_SEC;
start = clock();
float sumColMajor = 0;
for (int i=0; i<10; i++)
{
sumColMajor += computeSumColMajor(array, rows, cols);
}
end = clock();
double timeColMajor = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Row major %f, result %f\n", timeRowMajor, sumRowMajor);
printf("Col major %f, result %f\n", timeColMajor, sumColMajor);
return 0;
}
(如果我在这里违反了一些最佳做法,我很抱歉,我通常是一个Java人......)
对我来说,行主要访问速度比列主要访问速度快几个数量级。 当然,确切的数字将在很大程度上取决于目标系统,但所有目标的一般问题应该是相同的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.