克隆交错数组比多维数组慢

Cloning jagged array is slower than multidimensional array

我正在尝试克隆一个大小约为 100x100 的多维数组,我发现的每个资源似乎都表明使用锯齿状数组应该更有效(至少在查找中,因为多维数组使用函数-打电话)。

但我的问题是我对这些数组做了很多克隆,而且克隆锯齿状数组(在循环中分配新数组)似乎比只做 multArray.Clone() 慢得多。

示例代码:

class Program
    {
        static void Main(string[] args)
        {
            int matSize = 100;
            int iterations = 100000;
            Random r = new Random();
            Stopwatch sw = new Stopwatch();
            double[][] jaggedMat = new double[matSize][];
            double[,] multiMat = new double[matSize, matSize];
            for(int i = 0; i < matSize; i++)
            {
                jaggedMat[i] = new double[matSize];
                for (int j = 0; j < matSize; j++)
                {
                    double v = r.NextDouble();
                    jaggedMat[i][j] = v;
                    multiMat[i, j] = v;
                }
            }
            Console.WriteLine($"Cloning jagged matrix old school.");
            sw.Start();
            for (int i=0; i<iterations; i++)
            {
                double[][] copy = new double[matSize][];
                for(int j = 0; j <matSize; j++)
                {
                    copy[j] = new double[matSize];
                    for (int k = 0; k < matSize; k++)
                    {
                        copy[j][k] = jaggedMat[j][k];
                    }
                }
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.WriteLine($"Cloning using LINQ");
            sw.Reset();
            sw.Start();
            for (int i = 0; i < iterations; i++)
            {
                var clone = jaggedMat.Select(element => element.ToArray()).ToArray();
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.WriteLine($"Cloning multidimensional array.");
            sw.Reset();
            sw.Start();
            for(int i = 0; i < iterations; i++)
            {
                var clone = multiMat.Clone() as double[,];
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.ReadKey();
        }
    }

这会在我的计算机上产生以下输出:

克隆锯齿状矩阵老派。 克隆耗时 4913ms 使用 LINQ 克隆 克隆耗时 2283ms 克隆多维数组。 克隆耗时 712 毫秒

如您所见,在相同大小的矩阵上执行 .Clone() 比实际分配新的交错数组快约 3 倍。

有人知道是否有更快的克隆交错数组的方法吗?

我没有测量性能。但是您可以用更少的代码更简单地解决这个问题。我的解决方案序列化和反序列化整个数组以获得它的深层副本。

using System.Runtime.Serialization.Formatters.Binary;
BinaryFormatter formatter = new BinaryFormatter();
using(var ms = new MemoryStream())
{
   var array = new int[100, 100];
   array [0, 1] = 57; // simple test data to validate the output.
   formatter.Serialize(ms, array );
   ms.Position = 0; // rewind the stream to deserialize it.
   var copied = formatter.Deserialize(ms);
}

这样做:

double[][] copy = new double[matSize][];
for (int j = 0; j < matSize; j++)
{
    copy[j] = jaggedMat[j].Clone() as double[];
}

它会使锯齿状数组只比多维数组慢 2 倍(在我的机器上是 2450 毫秒对 1360 毫秒)。简单地说,创建 100 个对象(锯齿状数组的线)是有成本的。 GC 会有点讨厌你 :-) 如果 GC 运行,所有这些对象都必须分配然后释放。这使得锯齿状阵列克隆变慢。我会说有趣的是成本如此缓慢(似乎创建一个数组与填充它的成本相同,因为多维克隆是纯填充,而锯齿状数组克隆是一半复制一半创建数组)