为什么.NET中的多维数组比普通数组慢?
我试图用一个 盘陀今天的多维数组,当我注意到它的性能并不像我预期的那样。使用单维数组和手动计算索引要比使用2D数组快得多(几乎两倍)。我使用1024*1024
数组(初始化为随机值)编写了一个测试 ,进行了1000次迭代,我在我的机器上得到了以下结果:
sum(double[], int): 2738 ms (100%)sum(double[,]): 5019 ms (183%)sum(double[][]): 2540 ms ( 93%)
这是我的测试代码:
public static double sum(double[] d, int l1) { // assuming the array is rectangular double sum = 0; int l2 = d.Length / l1; for (int i = 0; i < l1; ++i) for (int j = 0; j < l2; ++j) sum += d[i * l2 + j]; return sum;}public static double sum(double[,] d) { double sum = 0; int l1 = d.GetLength(0); int l2 = d.GetLength(1); for (int i = 0; i < l1; ++i) for (int j = 0; j < l2; ++j) sum += d[i, j]; return sum;}public static double sum(double[][] d) { double sum = 0; for (int i = 0; i < d.Length; ++i) for (int j = 0; j < d[i].Length; ++j) sum += d[i][j]; return sum;}public static void Main() { Random random = new Random(); const int l1 = 1024, l2 = 1024; double[ ] d1 = new double[l1 * l2]; double[,] d2 = new double[l1 , l2]; double[][] d3 = new double[l1][]; for (int i = 0; i < l1; ++i) { d3[i] = new double[l2]; for (int j = 0; j < l2; ++j) d3[i][j] = d2[i, j] = d1[i * l2 + j] = random.NextDouble(); } // const int iterations = 1000; TestTime(sum, d1, l1, iterations); TestTime(sum, d2, iterations); TestTime(sum, d3, iterations);}
进一步研究表明,第二种方法的IL比第一种方法大23%。(代码大小68比52)这主要是由于呼叫System.Array::GetLength(int)
。编译器还发出呼吁Array::Get
为盘陀多维数组,而它只需要ldelem
简单的数组。
所以我想知道,为什么通过多维数组访问比普通数组更慢?我会假设编译器(或JIT)会做类似于我在第一种方法中所做的事情,但事实并非如此。
你能不能帮助我理解为什么会发生这种情况?