我有一些奇怪的性能结果,我不能完全解释。似乎这一行
d = new double[4, 4]{{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},};
比这个
慢4倍d = new double[4, 4];
d[0, 0] = 1; d[0, 1] = 0; d[0, 2] = 0; d[0, 3] = 0;
d[1, 0] = 0; d[1, 1] = 1; d[1, 2] = 0; d[1, 3] = 0;
d[2, 0] = 0; d[2, 1] = 0; d[2, 2] = 1; d[2, 3] = 0;
d[3, 0] = 0; d[3, 1] = 0; d[3, 2] = 0; d[3, 3] = 1;
(这甚至没有考虑到在这个例子中我可以忽略所有的= 0
赋值)
我知道在c#中,由于边界检查,在多维数组上循环可能很慢。但是这里没有循环,不需要边界检查,整个数组初始化行可以在编译时解析。
第二个代码块必须首先将数组初始化为0,然后分别覆盖每个值。
那么问题是什么呢?
我使用以下代码来度量性能:
using System;
using System.Diagnostics;
class Program
{
public static double[,] d; // global static variable to prevent the JIT optimizing it away
static void Main(string[] args)
{
Stopwatch watch;
int numIter = 10000000; // repeat all tests this often
double[,] d2 = new double[4, 4]{{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},};
// ================================================================
// use arrayInitializer: slowest
watch = Stopwatch.StartNew();
for (int i = 0; i < numIter; i++)
{
d = new double[4, 4]{{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},};
}
Console.WriteLine("ArrayInitializer: t{0:0.##########}ms", watch.ElapsedMilliseconds * 1.0 / numIter);
// ================================================================
// use Array.Copy: faster
watch = Stopwatch.StartNew();
for (int i = 0; i < numIter; i++)
{
d = new double[4, 4];
Array.Copy(d2, d, d2.Length);
}
Console.WriteLine("new + Array.Copy: t{0:0.##########}ms", watch.ElapsedMilliseconds * 1.0 / numIter);
// ================================================================
// direct assignment: fastest
watch = Stopwatch.StartNew();
for (int i = 0; i < numIter; i++)
{
d = new double[4, 4];
d[0, 0] = 1; d[0, 1] = 0; d[0, 2] = 0; d[0, 3] = 0;
d[1, 0] = 0; d[1, 1] = 1; d[1, 2] = 0; d[1, 3] = 0;
d[2, 0] = 0; d[2, 1] = 0; d[2, 2] = 1; d[2, 3] = 0;
d[3, 0] = 0; d[3, 1] = 0; d[3, 2] = 0; d[3, 3] = 1;
}
Console.WriteLine("direct assignment: t{0:0.##########}ms", watch.ElapsedMilliseconds * 1.0 / numIter);
}
}
结果:
ArrayInitializer: 0,0007917ms
new + Array.Copy: 0,0002739ms
direct assignment: 0,0002281ms
这里很好地解释了数组初始化式以及为什么会看到不同的结果:http://bartdesmet.net/blogs/bart/archive/2008/08/21/how-c-array-initializers-work.aspx
基本上-数组初始化涉及自定义结构的创建,而每个项的直接赋值只是在堆栈中直接赋值,尽管它更快。