【发布时间】:2010-09-15 04:43:03
【问题描述】:
在 C# 中使用二维数组 (type[,]) 还是数组数组 (type[][]) 性能更高?
特别是对于初始分配和项目访问
【问题讨论】:
标签: c# performance arrays
在 C# 中使用二维数组 (type[,]) 还是数组数组 (type[][]) 性能更高?
特别是对于初始分配和项目访问
【问题讨论】:
标签: c# performance arrays
当然,如果一切都失败了……测试一下!以下给出(在控制台的“发布”中):
Size 1000, Repeat 1000
int[,] set: 3460
int[,] get: 4036 (chk=1304808064)
int[][] set: 2441
int[][] get: 1283 (chk=1304808064)
所以锯齿状数组更快,至少在这个测试中是这样。有趣的!然而,这是一个相对很小的因素,所以我仍然会坚持更好地描述我的要求。除了一些特定的(高 CPU/处理)场景外,可读性/可维护性应该胜过小的性能提升。不过,这取决于你。
请注意,此测试假定您访问数组的次数比创建数组的次数要多,因此我没有包括创建时间,我会预计矩形会稍微快一些,除非内存高度碎片化.
using System;
using System.Diagnostics;
static class Program
{
static void Main()
{
Console.WriteLine("First is just for JIT...");
Test(10,10);
Console.WriteLine("Real numbers...");
Test(1000,1000);
Console.ReadLine();
}
static void Test(int size, int repeat)
{
Console.WriteLine("Size {0}, Repeat {1}", size, repeat);
int[,] rect = new int[size, size];
int[][] jagged = new int[size][];
for (int i = 0; i < size; i++)
{ // don't count this in the metrics...
jagged[i] = new int[size];
}
Stopwatch watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
rect[i, j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] set: " + watch.ElapsedMilliseconds);
int sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += rect[i, j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
jagged[i][j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] set: " + watch.ElapsedMilliseconds);
sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += jagged[i][j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
}
}
【讨论】:
我相信 [,] 可以分配一个连续的内存块,而 [][] 是 N+1 个块分配,其中 N 是第一个维度的大小。所以我猜想 [,] 在初始分配时更快。
Access 可能大致相同,只是 [][] 会涉及一个额外的取消引用。除非你处于一个非常紧的循环中,否则它可能是一个洗涤。现在,如果您正在执行诸如图像处理之类的事情,您在 之间 行而不是逐行遍历,则引用的局部性将发挥重要作用,并且 [,] 可能会超出 [][ ] 取决于您的缓存大小。
正如 Marc Gravell 所说,使用情况是评估性能的关键......
【讨论】:
这真的取决于。 MSDN 杂志文章 Harness the Features of C# to Power Your Scientific Computing Projects 是这样说的:
虽然矩形阵列在结构和性能方面通常优于锯齿阵列,但在某些情况下,锯齿阵列可能会提供最佳解决方案。如果您的应用程序不需要对数组进行排序、重新排列、分区、稀疏或较大,那么您可能会发现锯齿状数组的性能非常好。
【讨论】:
type[,] 会更快。不仅因为偏移量计算更少。主要是因为更少的约束检查,更少的内存分配和更大的内存本地化。 type[][] 不是单个对象——它是 1 + N 个必须分配的对象,并且可以彼此远离。
【讨论】: