繁体   English   中英

在C中使用x / y坐标索引2D数组的惯例是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM