在c#chat中一直在讨论这个问题。最初的问题是:
正在计算,例如(Int32)5 + 5快于1234723847 + 32489237?
我最初的想法是在二进制级别会优化以忽略填充零,因此较小的数字会更快。
所以,我测试了它。如果你有兴趣,这是程序。如果没有,请跳到结果。
Stopwatch sw = new Stopwatch();
Int64 c = 0;
long msDifferential = 0; //
int reps = 10; //number of times to run the entire program
for (int j = 0; j < reps; j++)
{
sw.Start(); //
sw.Stop(); // Just in case there's any kind of overhead for the first Start()
sw.Reset(); //
sw.Start(); //One hundred million additions of "small" numbers
for (Int64 i = 0, k = 1; i < 100000000; i++, k++)
{
c = i + k;
}
sw.Stop();
long tickssmall = sw.ElapsedTicks;
long mssmall = sw.ElapsedMilliseconds;
sw.Reset();
sw.Start(); //One hundred million additions of "big" numbers
for (Int64 i = 100000000000000000, k = 100000000000000001; i < 100000000100000000; i++, k++)
{
c = i + k;
}
sw.Stop();
long ticksbig = sw.ElapsedTicks;
long msbig = sw.ElapsedMilliseconds;
//total differentials for additions
ticksDifferential += ticksbig - tickssmall;
msDifferential += msbig - mssmall;
}
//average differentials per 100000000 additions
long averageDifferentialTicks = ticksDifferential / reps;
long averageDifferentialMs = msDifferential / reps;
//average differentials per addition
long unitAverageDifferentialTicks = averageDifferentialTicks / 100000000;
long unitAverageDifferentialMs = averageDifferentialMs / 100000000;
System.IO.File.AppendAllText(@"C:\Users\phillip.schmidt\My Documents\AdditionTimer.txt", "Average Differential (Ticks): " + unitAverageDifferentialTicks.ToString() + ", ");
System.IO.File.AppendAllText(@"C:\Users\phillip.schmidt\My Documents\AdditionTimer.txt", "Average Differential (Milliseconds): " + unitAverageDifferentialMs.ToString());
调试模式
发布模式(已启用优化)
发布模式(禁用优化)
因此,在调试模式下,“大”数字加起来大约需要2.17纳秒,而不是“小”数字。但是,在发布模式下,差异并不那么显着。
所以我有一些后续问题:
答案 0 :(得分:2)
特定优化的效果取决于您的编译器。您应该查看在每种情况下生成的汇编代码,并比较生成的CPU指令。在CPU级别,如果生成相同的指令,则在性能上应该没有任何差异,这取决于您添加的值。 CPU具有时钟信号,并且如果在相同大小的操作数上执行相同的指令,则无论操作数的位是1还是0,简单的算术运算都将采用相同数量的时钟周期。记忆效应可能会影响性能,但这里的数据足够小,可能并不重要。在反汇编中,您可以检查变量是否最终在寄存器中。如果没有,人们可能想知道是否只有一些变量对大数据起重要作用的影响(如缓存命中/未命中,物理内存访问等)在这里也很重要。它们可能,因为您的CPU每秒能够进行数十亿次算术运算,但RAM是外部设备,速度要慢得多。无论如何,这样的效果是随机的,并不取决于您添加的值是大还是小。同样应该用于管道停顿,指令重新排序等。在一系列实验中,在不同时间执行,平均时间应该在误差范围内相同(在释放模式中获得的差异肯定属于此类别)。 / p>
我看到可能存在差异的一种可能性是编译器,它不是直接通过64位指令而是使用多个32位指令来处理64位数字。在这种情况下,智能编译器可能会注意到在某个循环中使用的值永远不会超出32位数的限制,并且只发出一个32位值的指令,而不是两个32位值组成的值。 64位值。看看反汇编可以揭示是否是这种情况。