【发布时间】:2018-11-04 15:45:19
【问题描述】:
我正在尝试克隆一个大小约为 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 克隆多维数组。 克隆耗时 712ms
如您所见,在相同大小的矩阵上执行 .Clone() 比实际分配新的锯齿状数组快约 3 倍。
有人知道是否有更快的方法来克隆锯齿状数组吗?
【问题讨论】:
-
我希望您在发布模式下运行测试,并且没有调试器(CTRL+F5 或直接在命令行中)...而且我经常在测试开始时添加
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;, 以提高程序在运行期间的优先级 -
我会说克隆锯齿状数组应该更慢。请注意,您可以半克隆锯齿状数组(克隆每一行):
copy[j] = jagged[j].Clone as double[] -
其实我没有,从命令行运行测试产生了类似的结果:克隆锯齿状矩阵老派。克隆需要 3801 毫秒 使用 LINQ 克隆需要 1600 毫秒 克隆多维数组。克隆耗时 484 毫秒
-
在 Core i7 上使用 Benchmark.NET,10,000 次迭代得到以下结果:OldSchool:140.38 ms,Linq:151.74 ms,多:47.5 毫秒。
-
您基本上发现 Array.Clone() 在 CLR 内部进行了微优化,它可以使用原始 memcpy 来完成,而无需进行边界检查。你永远无法击败它。这也适用于锯齿状数组,但它的惊人速度可以帮助您发现 Clone() 的问题,它不是深拷贝。您通常希望避免索引 copy[j] 和 jaggedMat[j],它们是循环不变的。然而,抖动优化器可以自己解决这个问题。
标签: c# .net multidimensional-array jagged-arrays