【问题标题】:Is this 2D array initialization a bad idea?这个二维数组初始化是个坏主意吗?
【发布时间】:2011-02-20 00:16:50
【问题描述】:

我有一些需要二维数组的东西,但为了获得更好的缓存性能,我宁愿它实际上是一个普通数组。这是我的想法,但我不知道这是不是一个糟糕的想法:

const int XWIDTH = 10, YWIDTH = 10;
int main(){
    int * tempInts = new int[XWIDTH * YWIDTH];
    int ** ints = new int*[XWIDTH];
    for(int i=0; i<XWIDTH; i++){
        ints[i] = &tempInts[i*YWIDTH];
    }
    // do things with ints
    delete[] ints[0];
    delete[] ints;
    return 0;
}

所以我的想法是,我不是new一堆数组(并将它们放在内存中的不同位置),而是指向一个我一次创建的数组。

delete[] (int*) ints; 的原因是因为我实际上是在一个类中执行此操作,它会节省 [微不足道的] 内存而不是保存原始指针。

只是想知道是否有任何理由这是一个可怕的想法。或者,如果有更简单/更好的方法。目标是能够以ints[x][y] 而不是ints[x*YWIDTH+y] 访问数组。

编辑:一个简单的基准测试表明,我的方式在没有优化器的情况下更快,但 gcc 可能出于某种原因在简单方式上优化得更好。

http://pastebin.com/YDRuLuXv

如果你用gcc -O0编译,最好是stack,然后是mine,然后normal。如果你编译时 X_MAX 设置为大值,Y_MAX 设置为小值,并使用 gcc -O3,我的和堆栈应该真的很快,但正常的不会。如果你让 X_MAX 小而 Y_MAX 大,正常的方法应该会赢(甚至由于某种原因超过了堆栈方法)。

【问题讨论】:

    标签: c++ multidimensional-array memory-management


    【解决方案1】:

    这种方法的问题在于它容易出错。我会告诉你将分配和对 2D 数组中各个元素的访问封装在一个类中。

    class Array2D
    {
    private:
        /* Pointer necessary for the choosen implementation */
    public:
        Array2D(unsigned int dim1, unsigned int dim2);
        ~Array2D() /* Needed, since you will be allocation memory for this class */
        double operator()(unsigned int x, unsigned int y);
    }
    

    在这种情况下,如果您觉得需要更改分配,您只能更改方法实现,保持接口不变。您的其余代码实际上将仅使用 operator() 和构造函数。它还可以帮助您防止内存泄漏。

    【讨论】:

      【解决方案2】:

      我认为您在太早的阶段进行了不必要的微优化。不必担心这一点,只需以最简单的方式让程序正常工作即可。

      如果您需要一个二维数组,只需声明并使用它。减少错误和维护将比任何可能根本不存在的性能提升更值得。

      【讨论】:

      • 问题是它必须是动态的,你不能做new int[XWIDTH][YWIDTH];,现在这会更容易处理并且可能会在缓存性能上有所不同。主要的是它很容易,如果它有效,它至少不会伤害任何东西。
      • 如果要动态分配二维数组,只需使用 a = malloc(sizeof(int *) * ROWS); for (int i = 0; i
      • 我意识到我可以做到这一点,但这会创建 [行数] 单独的内存块(非连续)。我认为我应该用一大块获得更好的缓存性能。我会做一些基准测试,看看我是否能证明不同。
      • 我做了一些快速测试。我的方式通常得到了非常小的但一致的速度提升。大约 3%(在一个只分配一个巨大的 2D 数组然后将其元素相加的测试中)。
      • 我添加了我的基准的粘贴箱。随着X_MAX 变大,它对我的​​方式更有利。有趣的是,使用 gcc -O[1-3],当 Y_MAX 较小时,我的方法似乎得到了更好的优化(尝试 Y_MAX = 1; 然后使用 gcc -O3 编译),但如果 X_MAX > Y_MAX,简单的方法会更好。
      【解决方案3】:

      我找到了更好的方法。 Boost 有一个用于多维数组的库:boost::multi_array

      this question得到这个想法。

      【讨论】:

        猜你喜欢
        • 2011-10-10
        • 1970-01-01
        • 2012-11-29
        • 1970-01-01
        • 1970-01-01
        • 2021-04-04
        相关资源
        最近更新 更多