这些方法调用中的最后三个大约需要。时间是前四个的两倍。
唯一的区别是它们的参数不再适合整数。但这有关系吗?该参数被声明为 long,因此无论如何它都应该使用 long 进行计算。模运算是否对数字> maxint 使用另一种算法?
我正在使用 amd athlon64 3200+、winxp sp3 和 vs2008。
Stopwatch sw = new Stopwatch();
TestLong(sw, int.MaxValue - 3l);
TestLong(sw, int.MaxValue - 2l);
TestLong(sw, int.MaxValue - 1l);
TestLong(sw, int.MaxValue);
TestLong(sw, int.MaxValue + 1l);
TestLong(sw, int.MaxValue + 2l);
TestLong(sw, int.MaxValue + 3l);
Console.ReadLine();
static void TestLong(Stopwatch sw, long num)
{
long n = 0;
sw.Reset();
sw.Start();
for (long i = 3; i < 20000000; i++)
{
n += num % i;
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
编辑: 我现在对 C 进行了同样的尝试,但问题不会出现在这里,所有模运算都需要相同的时间,在发布和调试模式下,打开和不打开优化:
#include "stdafx.h"
#include "time.h"
#include "limits.h"
static void TestLong(long long num)
{
long long n = 0;
clock_t t = clock();
for (long long i = 3; i < 20000000LL*100; i++)
{
n += num % i;
}
printf("%d - %lld\n", clock()-t, n);
}
int main()
{
printf("%i %i %i %i\n\n", sizeof (int), sizeof(long), sizeof(long long), sizeof(void*));
TestLong(3);
TestLong(10);
TestLong(131);
TestLong(INT_MAX - 1L);
TestLong(UINT_MAX +1LL);
TestLong(INT_MAX + 1LL);
TestLong(LLONG_MAX-1LL);
getchar();
return 0;
}
编辑2:
谢谢你的好建议。我发现 .net 和 c(在调试模式和发布模式下)都没有使用原子 CPU 指令来计算余数,但它们调用了一个函数。
在 c 程序中,我可以得到它的名称,即“_allrem”。它还显示了该文件的完整源代码注释,因此我发现该算法是 32 位除数的特殊情况,而不是 .net 应用程序中的除数。
我还发现 c 程序的性能真的只受除数的值而不是被除数的影响。另一项测试表明,.net 程序中余数函数的性能取决于被除数和除数。
顺便说一句:即使是 long long 值的简单加法也是通过连续的 add 和 adc 指令计算的。因此,即使我的处理器称自己为 64 位,它确实不是 :(
编辑3:
我现在在使用 Visual Studio 2010 编译的 Windows 7 x64 版本上运行 c 应用程序。有趣的是,性能行为保持不变,尽管现在(我检查了汇编源代码)使用了真正的 64 位指令。