Хорошо, во-первых, я не знаю, как компиляторы делают это автоматически. И я уверен, что есть хотя бы 10, если не 100 алгоритмов, из которых приходится выбирать компиляторам.
И в любом случае это, вероятно, зависит от компилятора.
Но я могу помочь вам с расчетом его эффективности.
Просто отметьте, что эта техника обычно не дает вам большого прироста производительности.
Но при повторных зацикленных расчетах и может дать высокий процент производительности.
Это потому, что обычно функция внутри цикла занимает гораздо больше времени вычислений, чем проверка состояния цикла.
Итак, допустим, у нас есть простой цикл с константой, потому что вам было лень копировать-вставлять или просто думали, что это будет выглядеть лучше:
for (int i = 0; i < 5; i++)
{
DoSomething();
}
Здесь у вас есть 5 int сравнений, 5 приращений и 5 DoSomethig () вызовов.
Так что если DoSomething () работает относительно быстро, то мы получаем 15 операций.
Теперь, если вы развернете это, вы уменьшите его до 5 операций:
DoSomething();
DoSomething();
DoSomething();
DoSomething();
DoSomething();
Теперь с константами это проще, поэтому давайте посмотрим, как это будет работать с переменной:
for (int i = 0; i < n; i++)
{
DoSomething();
}
Здесь у вас есть n int сравнений, n приращений и n DoSomethig () вызывает = 3n .
Теперь мы не можем развернуть его полностью, но мы можем развернуть его с постоянным коэффициентом (чем выше ожидаемое значение n , тем больше мы должны развернуть его):
int i;
for (i = 0; i < n; i = i+3)
{
DoSomething();
DoSomething();
DoSomething();
}
if (i - n == 2)
{
DoSomething(); // We passed n by to, so there's one more left
}
else if (i - n == 1)
{
DoSomething(); //We passed n by only 1, so there's two more left
DoSomething();
}
Теперь у нас есть Здесь у вас есть n / 3 + 2 int сравнения, n / 3 приращений и n DoSomethig () вызывает = (1 2/3) * n .
Мы спасли себя (1 1/3) * n операций. Что сокращает время вычислений почти вдвое.
К вашему сведению, еще один метод аккуратного развертывания называется Устройство Даффа .
Но это очень специфично для компилятора и конкретной языковой реализации. Есть языки, где это было бы на самом деле хуже.