我试图克隆一个大小约为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();
}
}
这会在我的电脑上产生以下输出:
克隆参差不齐的矩阵老派。 克隆需要4913毫秒 使用LINQ进行克隆 克隆花了2283ms 克隆多维数组。 克隆需要712ms
正如您所看到的,在相同大小的矩阵上执行.Clone()的速度比实际分配新的锯齿状数组快约3倍。
任何人都知道是否有更快的方法来克隆锯齿状阵列?
答案 0 :(得分:2)
这样做:
double[][] copy = new double[matSize][];
for (int j = 0; j < matSize; j++)
{
copy[j] = jaggedMat[j].Clone() as double[];
}
它会使锯齿状阵列比多维阵列慢2倍(在我的机器上2450ms对比1360ms)。简而言之,创建100个对象(锯齿状阵列的线条)会产生成本。 GC会讨厌你:-)所有这些对象都必须分配,然后在GC运行时释放。这使得锯齿状阵列克隆速度变慢。我说有趣的是成本是如此之慢(似乎创建一个阵列与填充它的成本相同,因为多维克隆是纯粹的填充,而锯齿状阵列克隆是半复制和一半创建数组)
答案 1 :(得分:0)
我没有测量过表现。但是你可以用更少的代码来解决这个问题。我的解决方案序列化和反序列化整个数组以获得它的深层副本。
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);
}