c# 聊天中对此进行了持续的讨论。最初的问题是这样的:
Is calculating e.g. (Int32) 5+5 faster then 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());
结果
Debug模式
- 平均单位差异:2.17 纳秒
Release模式(启用优化)
- 平均单位差异:0.001 纳秒
Release模式(禁用优化)
- 平均单位差异:0.01 纳秒
因此,在 Debug模式下,每次相加,“大”数字相加所需时间比“小”数字长约 2.17 纳秒。然而,在 Release模式下,差异并不那么显着。
问题
所以我有一些后续问题:
- 哪种模式最适合我的目的? (调试、发布、发布(无选项))
- 我的结果准确吗?如果是这样,速度差异的原因是什么?
- 为什么 Debug模式下的差异如此之大?
- 还有什么我应该考虑的吗?
最佳答案
具体优化的效果取决于您的编译器。您应该查看每种情况下生成的汇编代码并比较生成的 CPU 指令。在 CPU 级别,如果生成相同的指令,则根据您添加的值,性能不应有任何差异。 CPU 有一个时钟信号,如果在相同大小的操作数上执行相同的指令,则无论操作数的位是 1 还是 0,简单的算术运算都将花费相同数量的时钟周期。内存效应可能会影响性能,但这里的数据足够小,因此这可能并不重要。在反汇编中,您可以检查变量是否最终出现在寄存器中。如果不是,人们可能会想,仅用几个变量对较大数据(如缓存命中/未命中、物理内存访问等)发挥重要作用的影响是否也很重要。他们可能会这样做,因为你的 CPU 每秒能够进行数十亿次算术运算,但 RAM 是一个外部设备,速度要慢得多。无论如何,这种影响是随机的,并不取决于您添加的值是大还是小。管道停顿、指令重新排序等也应该如此。在不同时间执行的一系列实验中,平均时间在误差范围内应该是相同的(在 Release模式下获得的差异肯定属于这一类)。
我发现可能存在差异的一种可能性是编译器不是直接通过 64 位指令处理 64 位数字,而是使用多个 32 位指令。在这种情况下,智能编译器可能会注意到您在某些循环中使用的值永远不会超出 32 位数字的限制,并发出仅对单个 32 位值而不是对构成 32 位值的两个 32 位值进行操作的指令。 64 位值。看看反汇编就可以知道情况是否如此。
关于performance - 小数相加比大数相加快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12411113/