我想弄清楚为什么"选择A"表现得更好"选择B".我的测试显示了228 vs 830或类似的东西,它就像是4倍的差异.看着IL,未经训练的眼睛不会在两个电话之间巧妙地挑选出来.
谢谢你,斯蒂芬
const int SIZE = 10000;
void Main()
{
var sw = Stopwatch.StartNew();
int[,]A = new int[SIZE, SIZE];
int total, x, y;
// Choice A
total = 0;
for (x = 0; x < SIZE; x++)
{
for (y = 0; y < SIZE; y++)
{
total += A[x, y];
}
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
// Choice B
total = 0;
for (y = 0; y < SIZE; y++)
{
for (x = 0; x < SIZE; x++)
{
total += A[x, y];
}
}
Console.WriteLine(sw.ElapsedMilliseconds);
}
// Define other methods and classes here
Run Code Online (Sandbox Code Playgroud)
好吧,我把它打破了,以便它们可以彼此独立运行并减轻任何缓存和/或诊断......并且B总是在A后面进入
namespace ConsoleApplication1
{
class ProgramA
{
const int SIZE = 10000;
static void Main(string[] args)
{
var sw = Stopwatch.StartNew();
int[,] A = new int[SIZE, SIZE];
int total, x, y;
// Choice A
total = 0;
for (x = 0; x < SIZE; x++)
{
for (y = 0; y < SIZE; y++)
{
total += A[x, y];
}
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadLine();
}
}
class ProgramB
{
const int SIZE = 10000;
static void Main(string[] args)
{
var sw = Stopwatch.StartNew();
int[,] A = new int[SIZE, SIZE];
int total, x, y;
// Choice B
total = 0;
for (y = 0; y < SIZE; y++)
{
for (x = 0; x < SIZE; x++)
{
total += A[x, y];
}
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
猜测一下,缓存效果在这里会很重要.
二维数组在内存中如下所示:
(0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) ...
Run Code Online (Sandbox Code Playgroud)
在选项A中,您正在访问内存中的连续元素 - 这意味着当CPU获取缓存行时,它会获得几个连续的元素.选项B通过内存跳转.因此,一旦阵列变得大于高速缓存大小,选项B就需要更多的存储器访问.