【问题标题】:Performance of 2-dimensional array vs 1-dimensional array二维数组与一维数组的性能
【发布时间】:2010-11-17 13:56:43
【问题描述】:

在 C 中,m×n 二维数组与长度为 m×n 的一维数组(对于较大的 m 和 n 值)在时间和空间上是否存在差异?使用一维数组访问元素会更快吗?

【问题讨论】:

    标签: c arrays


    【解决方案1】:

    在 C 中,二维数组只是一维数组的一种简洁的索引方案。就像一维数组一样,二维数组分配一块连续的内存,A[row][col] 表示法类似于A[row*NCOLS+col]

    通常,如果您要使用一维数组实现自己的多维数组,您会编写一个索引函数:

    int getIndex(int row, int col) { return row*NCOLS+col; }
    

    假设你的编译器内联了这个函数,这里的性能将与你使用二维数组的内置“索引函数”完全相同。

    举例说明:

    #define NROWS 10
    #define NCOLS 20
    

    这个:

    int main(int argc, char *argv[]) {
        int myArr[NROWS*NCOLS];
        for (int i=0; i<NROWS; ++i) {
           for (int j=0; j<NCOLS; ++j) {
              myArr[getIndex(i,j)] = i+j;
           }
        }
        return 0;
    }
    

    应该执行与此相同的操作:

    int main(int argc, char *argv[]) {
        int myArr[NROWS][NCOLS];
        for (int i=0; i<NROWS; ++i) {
           for (int j=0; j<NCOLS; ++j) {
              myArr[i][j] = i+j;
           }
        }
        return 0;
    }
    

    虽然AraKpointed out,如果你经常在行中跳转,并且行非常大,你可能会遇到很多页面错误......在这种情况下,自定义索引功能(带有行和cols 切换)可能会有所帮助,但也可以简单地更改将二维数组中的哪些维度视为行以及将哪些维度视为列。

    【讨论】:

      【解决方案2】:

      其实,如果你在C中使用所谓的二维数组,编译器会帮你映射成一维数组。如果你用一维数组,又想把它当成二维数组,那你就得自己写映射了。

      您唯一需要注意的是您应该逐行访问数组,因为 C 编译器将逐行存储您的二维数组。如果您按列访问“大”二维数组,则可能会发生页面错误。即使您使用仅支持一维数组的语言进行编程,您也可以轻松地将映射写入任意维数。

      如果您想做mapping row-wise,请查看这篇维基百科文章。您的映射可以是按列的,例如 FORTRAN 矩阵。

      【讨论】:

        【解决方案3】:

        罗伯特是正确的。索引表达式被编译为指针算术表达式,因此没有区别。

        然而,可能会产生影响的是访问顺序,因此您可能希望自己实现一些东西,以便您可以控制访问顺序。例如列优先与行优先形式。

        在现代处理器上,以不同的步长访问大型数组可能会产生意想不到的性能差异。顺序访问总是最快的,由于缓存交互,其他步幅可能会慢 30 倍。内部维度是 2 的幂的多维数组通常性能较差,因为它们与缓存关联性交互的方式。要了解这些问题,没有什么可以真正替代进行测量。

        【讨论】:

        • 你不需要自己写来决定布局; C 内置的布局是明确定义的。您可以通过编写array[row][column]array[column][row] 来选择使用哪个
        • 是的,没错。我应该给出一个更好的例子,比如块矩阵的各种方案。
        【解决方案4】:

        我认为没有任何区别。在内部,c 将二维数组视为依次排列的多个一维数组。

        但是,与所有事物的性能一样,您的里程可能会有所不同。可能存在某种微妙的指针算术差异。在这两种情况下运行定时测试。谁跑得快谁就赢了。

        【讨论】:

        • 难道你不能在 C 中也实现数组,例如 int **array 然后你 array = malloc(sizeof(int*)*rows); for (i = 0; i &lt; rows; ++i) { array[i] = malloc(sizeof(int) * cols); } 的优点是虽然访问和创建速度较慢,但​​添加行要快得多?
        • @derobert:这种结构通常被称为“参差不齐的数组”。它具有类似的语法访问,但实际上与普通的二维数组不同。
        • @dmckee 衣衫褴褛还是锯齿状?
        【解决方案5】:

        正如其他人所说,真正的区别在于您访问项目的方式:如果您的项目在内存中的布局方式是线性的,至少在常见架构上是线性的,那么重要的是。所以你真正拥有的只是一维数组,二维等......“只是”一种便利,一个合理的编译器应该优化索引 - 但实际上,一旦你有多个变量,编译器通常会在 arch 上失败喜欢 x86,因为寄存器不足。

        现在,这取决于您的应用程序,但我认为您应该默认使用一维布局,尤其是在您需要处理多个维度时。 C 中多维数组的第一个问题是您无法动态分配它们——如果您基于每行进行分配,您的性能将会很糟糕,因为您没有一块连续的内存。有关详细信息,请参阅FFTW doc

        请注意,您始终可以使用方便的数组索引来描述您的单块内存(您分配一个大的 nxm 内存块,然后创建一个包含 n 指向每一行的指针的数组)。

        【讨论】:

          【解决方案6】:

          我只是猜测,但我想说一维数组比二维数组快。但是,它不会更快。有点像 1,000,000.01 美元超过 1,000,000 美元。

          我会使用任何更容易编码的东西。

          【讨论】:

            猜你喜欢
            • 2013-05-19
            • 1970-01-01
            • 2013-09-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-10
            • 2011-12-18
            • 1970-01-01
            相关资源
            最近更新 更多