【发布时间】:2014-02-22 03:51:59
【问题描述】:
一些迭代器更快。我之所以发现这一点,是因为我在 Channel 9 上收到 Bob Tabor 的来信,告诉我不要复制和粘贴。
我习惯做这样的事情来设置数组值:
testArray[0] = 0;
testArray[1] = 1;
这是一个简化的示例,但为了不复制和粘贴,或者不再次输入内容,我想我应该使用循环。但是我有一种烦人的感觉,即循环比简单地列出命令要慢,而且看起来我是对的:列出东西要快得多。在我的大多数试验中,速度从最快到最慢是列表、do 循环、for 循环,然后是 while 循环。
为什么列出东西比使用迭代器更快,为什么迭代器的速度不同?
如果我没有以最有效的方式使用这些迭代器,请帮助我。
这是我的结果(对于 2 int 数组),下面是我的代码(对于 4 int 数组)。我在 Windows 7 64 位上尝试了几次。
要么我不擅长迭代,要么使用迭代器没有想象中的那么好。请让我知道它是什么。非常感谢。
int trials = 0;
TimeSpan listTimer = new TimeSpan(0, 0, 0, 0);
TimeSpan forTimer = new TimeSpan(0, 0, 0, 0);
TimeSpan doTimer = new TimeSpan(0, 0, 0, 0);
TimeSpan whileTimer = new TimeSpan(0, 0, 0, 0);
Stopwatch stopWatch = new Stopwatch();
long numberOfIterations = 100000000;
int numElements = 4;
int[] testArray = new int[numElements];
testArray[0] = 0;
testArray[1] = 1;
testArray[2] = 2;
testArray[3] = 3;
// List them
stopWatch.Start();
for (int x = 0; x < numberOfIterations; x++)
{
testArray[0] = 0;
testArray[1] = 1;
testArray[2] = 2;
testArray[3] = 3;
}
stopWatch.Stop();
listTimer += stopWatch.Elapsed;
Console.WriteLine(stopWatch.Elapsed);
stopWatch.Reset();
// for them
stopWatch.Start();
int q;
for (int x = 0; x < numberOfIterations; x++)
{
for (q = 0; q < numElements; q++)
testArray[q] = q;
}
stopWatch.Stop();
forTimer += stopWatch.Elapsed;
Console.WriteLine(stopWatch.Elapsed);
stopWatch.Reset();
// do them
stopWatch.Start();
int r;
for (int x = 0; x < numberOfIterations; x++)
{
r = 0;
do
{
testArray[r] = r;
r++;
} while (r < numElements);
}
stopWatch.Stop();
doTimer += stopWatch.Elapsed;
Console.WriteLine(stopWatch.Elapsed);
stopWatch.Reset();
// while
stopWatch.Start();
int s;
for (int x = 0; x < numberOfIterations; x++)
{
s = 0;
while (s < numElements)
{
testArray[s] = s;
s++;
}
}
stopWatch.Stop();
whileTimer += stopWatch.Elapsed;
Console.WriteLine(stopWatch.Elapsed);
stopWatch.Reset();
Console.WriteLine("listTimer");
Console.WriteLine(listTimer);
Console.WriteLine("forTimer");
Console.WriteLine(forTimer);
Console.WriteLine("doTimer");
Console.WriteLine(doTimer);
Console.WriteLine("whileTimer");
Console.WriteLine(whileTimer);
Console.WriteLine("Enter any key to try again the program");
Console.ReadLine();
trials++;
当我尝试使用 4 元素数组时,结果似乎更加明显。
我认为只有通过像其他试验一样的变量分配 listThem 组的值才是公平的。它确实使 listThem 组慢了一点,但它仍然是最快的。以下是几次尝试后的结果:
以下是我实现列表的方式:
int w = 0;
for (int x = 0; x < numberOfIterations; x++)
{
testArray[w] = w;
w++;
testArray[w] = w;
w++;
testArray[w] = w;
w++;
testArray[w] = w;
w = 0;
}
我知道这些结果可能是特定于实现的,但您会认为 Microsoft 会警告我们每个循环在速度方面的优缺点。你怎么看?谢谢。
更新:根据我发布的代码和列表仍然比循环更快,但循环在性能上似乎更接近。循环从最快到最慢:for、while 和 do。这有点不同,所以我的猜测是 do 和 while 的速度基本相同,而且 for 循环比 do 和 while 循环快大约 0.5%,至少在我的机器上是这样。以下是一些试验的结果:
【问题讨论】:
-
您正在展开 List 循环而不是其他循环。这是一种非常基本的优化技术,到处都在使用。当然不是微软隐藏的东西!
-
您可以尝试将
numElements的用法更改为硬编码数字(或将其更改为const)吗?然后编译器可能会决定展开内部循环。 -
为了清楚起见,您所说的速度差异超过 1.709 秒 一亿 次迭代。这意味着每个元素的差异是 0.00001709121 MILLISECONDS。换句话说..
WHO CARES。One method versus another makes no practical difference. -
@Dan-o,这是一个玩具程序 - 但像这样的紧密循环可能会深埋在一些真正的算法代码中,它会迭代一些巨大的数据结构。在这种情况下,秒数很快就会增加。
-
@sinelaw:当然……但是您在这里谈论的只是变量分配。实际上并未使用变量。因此,我们必须飞跃到一个用 C# 编写的真实世界应用程序,该应用程序对数组进行超过 1 亿次赋值。有比这更大的问题。在这种情况下,.NET 框架确实是错误的工具。
标签: c# performance iterator