【问题标题】:Multi-dimensional array vs. One-dimensional多维数组与一维
【发布时间】:2011-03-29 16:46:28
【问题描述】:

这基本上是对这个问题的重述:Java: Multi-dimensional array vs. One-dimensional 但对于 C#。

我有一定数量的元素可以存储为网格。 我应该使用数组[x*y] 还是数组[x][y]?

编辑:哦,所以有一维数组[x*y]、多维数组[x,y]和锯齿形数组[x][y],我可能想要锯齿形?

【问题讨论】:

  • 我会将multidimensional 数组标记为array[x,y] 而不是array[x][y]
  • 锯齿状数组更适合 Linq。

标签: c# arrays performance multidimensional-array


【解决方案1】:

在 C# 中使用 jagged arrays (array[][]) 有很多优点。它们实际上通常会胜过多维数组。

话虽如此,我个人会使用多维或锯齿状数组而不是一维数组,因为这更接近问题空间。使用一维数组会增加实现的复杂性,但不会提供真正的好处,尤其是与二维数组相比,因为在内部,它仍然是一个内存块。

【讨论】:

  • 抱歉,我讨厌“锯齿状阵列”这个词。 .net 文档抛出了太多的术语,以至于有人会认为锯齿状数组是一种新的数据类型。它只是一个数组 dangit 的数组!
  • @JonH:是的,但这是官方术语,CLR 中针对它们进行了特定的优化。
【解决方案2】:

我对不合理的大数组进行了测试,并惊讶地发现锯齿状数组 ([y][x]) 似乎比使用手动乘法 [y * ySize + x] 的一维数组更快。并且多维数组 [,] 速度较慢,但​​没有那么慢。

当然,您必须在您的特定阵列上进行测试,但看起来差异并不大,因此您应该使用最适合您的方法。

0.280 (100.0% | 0.0%) 'Jagged array 5,059x5,059 - 25,593,481'
|       0.006 (2.1% | 2.1%) 'Allocate'
|       0.274 (97.9% | 97.9%) 'Access'


0.336 (100.0% | 0.0%) 'TwoDim array 5,059x5,059 - 25,593,481'
|       0.000 (0.0% | 0.0%) 'Allocate'
|       0.336 (99.9% | 99.9%) 'Access'


0.286 (100.0% | 0.0%) 'SingleDim array 5,059x5,059 - 25,593,481'
|       0.000 (0.1% | 0.1%) 'Allocate'
|       0.286 (99.9% | 99.9%) 'Access'



0.552 (100.0% | 0.0%) 'Jagged array 7,155x7,155 - 51,194,025'
|       0.009 (1.6% | 1.6%) 'Allocate'
|       0.543 (98.4% | 98.4%) 'Access'


0.676 (100.0% | 0.0%) 'TwoDim array 7,155x7,155 - 51,194,025'
|       0.000 (0.0% | 0.0%) 'Allocate'
|       0.676 (100.0% | 100.0%) 'Access'


0.571 (100.0% | 0.0%) 'SingleDim array 7,155x7,155 - 51,194,025'
|       0.000 (0.1% | 0.1%) 'Allocate'
|       0.571 (99.9% | 99.9%) 'Access'



for (int i = 6400000; i < 100000000; i *= 2)
{
    int size = (int)Math.Sqrt(i);
    int totalSize = size * size;

    GC.Collect();

    ProfileTimer.Push(string.Format("Jagged array {0:N0}x{0:N0} - {1:N0}", size, totalSize));

    ProfileTimer.Push("Allocate");

    double[][] Jagged = new double[size][];
    for (int x = 0; x < size; x++)
    {
        Jagged[x] = new double[size];
    }

    ProfileTimer.PopPush("Allocate", "Access");

    double total = 0;
    for (int trials = 0; trials < 10; trials++)
    {
        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                total += Jagged[y][x];
            }
        }
    }

    ProfileTimer.Pop("Access");
    ProfileTimer.Pop("Jagged array");


    GC.Collect();

    ProfileTimer.Push(string.Format("TwoDim array {0:N0}x{0:N0} - {1:N0}", size, totalSize));

    ProfileTimer.Push("Allocate");

    double[,] TwoDim = new double[size,size];

    ProfileTimer.PopPush("Allocate", "Access");

    total = 0;
    for (int trials = 0; trials < 10; trials++)
    {
        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                total += TwoDim[y, x];
            }
        }
    }

    ProfileTimer.Pop("Access");
    ProfileTimer.Pop("TwoDim array");


    GC.Collect();

    ProfileTimer.Push(string.Format("SingleDim array {0:N0}x{0:N0} - {1:N0}", size, totalSize));

    ProfileTimer.Push("Allocate");

    double[] Single = new double[size * size];

    ProfileTimer.PopPush("Allocate", "Access");

    total = 0;
    for (int trials = 0; trials < 10; trials++)
    {
        for (int y = 0; y < size; y++)
        {
            int yOffset = y * size;
            for (int x = 0; x < size; x++)
            {
                total += Single[yOffset + x];
            }
        }
    }

    ProfileTimer.Pop("Access");
    ProfileTimer.Pop("SingleDim array");
}

【讨论】:

  • 非常有趣的帖子。我在 code.google.com 上找到了 ProfileTimer。起初我无法重现你的结果。锯齿状数组的内存分配非常慢,2-dim 访问非常慢。然后我在构建选项中取消选中“首选 32 位”,一切都非常符合您的结果。
【解决方案3】:

array[x,y] 的优点:
- 运行时将为您执行更多检查。将检查每个索引访问是否在允许的范围内。使用另一种方法,您可以轻松地做类似a[y*numOfColumns + x] 之类的事情,其中​​ x 可以超过“列数”,并且此代码将提取一些错误值而不会引发异常。
- 更清晰的索引访问a[x,y]a[y*numOfColumns + x] 干净

array[x*y] 的优点:
- 整个数组的迭代更容易。你只需要一个循环而不是两个。

获胜者是......我更喜欢array[x,y]

【讨论】:

    猜你喜欢
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 2017-01-24
    • 2012-08-03
    • 1970-01-01
    • 2012-01-03
    相关资源
    最近更新 更多