Последние три вызова этих методов занимают прибл. вдвое больше, чем первые четыре.
Единственная разница в том, что их аргументы больше не помещаются в целое число. Но должно ли это иметь значение? Параметр объявлен длинным, поэтому для расчета в любом случае следует использовать 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 (как в режиме отладки, так и в режиме выпуска) не используют атомарные инструкции процессора для вычисления остатка, но они вызывают функцию, которая это делает.
В программе c я мог получить ее имя - "_allrem". Он также отображал полные комментарии к источнику для этого файла, поэтому я нашел информацию, что этот алгоритм использует 32-битные делители вместо дивидендов, как это было в приложении .net.
Я также обнаружил, что на производительность программы c действительно влияет только значение делителя, но не дивиденд. Другой тест показал, что производительность функции остатка в программе .net зависит как от делимого, так и от делителя.
Кстати: даже простое сложение длинных длинных значений вычисляется последовательными инструкциями add и adc. Так что даже если мой процессор называет себя 64-битным, на самом деле это не так :(
РЕДАКТИРОВАТЬ3:
Теперь я запустил приложение c в версии Windows 7 x64, скомпилированной с помощью Visual Studio 2010. Забавно то, что поведение производительности остается прежним, хотя теперь (я проверил исходный код сборки) используются настоящие 64-битные инструкции.