在性能方面,什么更好?类型 [,] 或类型 [][]

本文关键字:类型 更好 性能 方面 什么 | 更新日期: 2023-09-27 17:47:21

C#中拥有二维数组(type[,])或数组数组(type[][])的性能更高吗?

特别是对于初始分配和项目访问

在性能方面,什么更好?类型 [,] 或类型 [][]

当然,如果所有其他方法都失败了...测试一下!下面给出(在控制台的"发布"中):

Size 1000, Repeat 1000
    int[,] set: 3460
    int[,] get: 4036 (chk=1304808064)
    int[][] set: 2441
    int[][] get: 1283 (chk=1304808064)

因此,锯齿状数组更快,至少在此测试中是这样。有趣!但是,这是一个相对较小的因素,因此我仍然会坚持使用更能描述我的要求的因素。除了某些特定的(高 CPU/处理)方案外,可读性/可维护性应该胜过小幅的性能提升。不过,由你决定。

请注意,此测试假设您访问数组的频率比创建数组的频率高得多,因此我没有包括创建时间,除非内存高度碎片化,否则我希望矩形会稍微快一些。

using System;
using System.Diagnostics;
static class Program
{
    static void Main()
    {
        Console.WriteLine("First is just for JIT...");
        Test(10,10);
        Console.WriteLine("Real numbers...");
        Test(1000,1000);
        Console.ReadLine();
    }
    static void Test(int size, int repeat)
    {
        Console.WriteLine("Size {0}, Repeat {1}", size, repeat);
        int[,] rect = new int[size, size];
        int[][] jagged = new int[size][];
        for (int i = 0; i < size; i++)
        { // don't count this in the metrics...
            jagged[i] = new int[size];
        }
        Stopwatch watch = Stopwatch.StartNew();
        for (int cycle = 0; cycle < repeat; cycle++)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    rect[i, j] = i * j;
                }
            }
        }
        watch.Stop();
        Console.WriteLine("'tint[,] set: " + watch.ElapsedMilliseconds);
        int sum = 0;
        watch = Stopwatch.StartNew();
        for (int cycle = 0; cycle < repeat; cycle++)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    sum += rect[i, j];
                }
            }
        }
        watch.Stop();
        Console.WriteLine("'tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
        watch = Stopwatch.StartNew();
        for (int cycle = 0; cycle < repeat; cycle++)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    jagged[i][j] = i * j;
                }
            }
        }
        watch.Stop();
        Console.WriteLine("'tint[][] set: " + watch.ElapsedMilliseconds);
        sum = 0;
        watch = Stopwatch.StartNew();
        for (int cycle = 0; cycle < repeat; cycle++)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    sum += jagged[i][j];
                }
            }
        }
        watch.Stop();
        Console.WriteLine("'tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
    }
}
我相信

[,] 可以分配一个连续的内存块,而 [][] 是 N+1 个块分配,其中 N 是第一维的大小。所以我猜 [,] 在初始分配时更快。

访问可能大致相同,只是 [][] 将涉及一个额外的取消引用。除非你处于一个特别紧的循环中,否则它可能是洗涤。现在,如果您正在执行图像处理之类的操作,其中在行之间引用而不是逐行遍历,则引用位置将发挥很大作用,并且 [,] 可能会根据您的缓存大小而边缘化 [][]。

正如Marc Gravell所提到的,使用是评估性能的关键......

这真的取决于。MSDN 杂志的文章"利用 C# 的功能来支持您的科学计算项目"是这样说的:

尽管矩形数组在结构和性能方面通常优于交错数组,但在某些情况下,交错数组可能会提供最佳解决方案。如果您的应用程序不需要对数组进行排序、重新排列、分区、稀疏或大型,那么您可能会发现交错数组的性能非常好。

type[,]将工作得更快。不仅因为偏移计算较少。主要是因为更少的约束检查、更少的内存分配和更多的内存本地化。type[][] 不是单个对象 - 它是必须分配的 1 + N 个对象,并且可以彼此远离。