Возможная оптимизация в моем коде?
Для того, чтобы решитьПроект Эйлера, задача № 5Я написал следующую программу:
class p5
{
const int maxNumber = 20;
static void Main(string[] args)
{
Job(); // First warm-up call to avoid Jit latency
var sw = Stopwatch.StartNew();
var result = Job();
sw.Stop();
Debug.Assert(result == 232792560);
Console.WriteLine(result);
Console.WriteLine(sw.Elapsed);
Console.ReadLine();
}
private static int Job()
{
var result = Enumerable.Range(1, int.MaxValue - 1)
.Where(
n => Enumerable.Range(maxNumber / 2 + 1, maxNumber / 2).All(c => n % c == 0)
).First();
return result;
}
}
Тем не менее, я обнаружил, что это немного долго (17 секунд, в режиме релиза), даже если это работает.
Есть ли возможная оптимизация?
К вашему сведению, я пытался сAsParallel
метод, но, как и ожидалось, кусок работ слишком мал, и переключение контекста было тяжелее, чем преимущества (более 1 минуты):
var result = Enumerable.Range(1, int.MaxValue - 1).AsParallel()
.Where(
n => Enumerable.Range(maxNumber / 2 + 1, maxNumber / 2).All(c => n % c == 0)
).First();
return result;
[Редактировать] Согласно предложению Мартина, эта версия делится на 10 времени:
private static int Job()
{
var n =2;
bool result;
do
{
result = true;
for (int c = maxNumber / 2; c <= maxNumber; c++)
{
if (n % c > 0)
{
result = false;
break;
}
}
n ++;//= 2;
} while (!result);
return n;
}
[Редактировать] Подводя итог всем моим тестам, приблизительное время выполнения:
Моя первая реализация: 20 секундУдален внутренний вызов enumerable.Range (заменен простым циклом for): 3 секундыУдален внешний и внутренний перечислимый. Вызов диапазона: 1,5 секунды.Только взятие четных чисел: (только с циклами, без enumerable.range): менее 1 секундыИспользование евклидовых алгоритмов Gcd / LCm согласно предложению drhirsch: 0,004 мсПоследнее предложение явно хороший ответ. Я благодарю drhirsch за то, что он предложил другой подход вместо простой оптимизации цикла