2013-03-25 5 views
16

я измерил время выполнения двух способов расчета мощности 2:C#: Почему вызов функции быстрее, чем ручной встраивание?

1) инлайн

result = b * b; 

2) С помощью простого вызова функции

result = Power(b); 

При работе в режиме отладки все выглядит так, как ожидалось: вызов функции значительно дороже, чем вычисление в строке (385 мс в строке против вызова функции 570 мс).

В режиме освобождения я ожидаю, что компилятор значительно ускорит время выполнения вызова функции, потому что компилятор встроил в себя очень маленькую функцию Power(). Но я не ожидал, что вызов функции будет более быстрым, чем ручной расчет.

Самое удивительное в этом случае: в сборке релизов первый запуск требует 109 мс, а второй запуск с вызовом Power() - всего 62 мс.

Как вызов функции быстрее, чем ручной встраивание?

Вот программа для воспроизведения:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Starting Test"); 

     // 1. Calculating inline without function call 
     Stopwatch sw = Stopwatch.StartNew(); 

     for (double d = 0; d < 100000000; d++) 
     { 
      double res = d * d; 
     } 

     sw.Stop(); 
     Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); 

     // 2. Calulating power with function call 
     Stopwatch sw2 = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      double res = Power(d); 
     } 

     sw2.Stop(); 
     Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); 

     Console.ReadKey(); 
    } 

    static double Power(double d) 
    { 
     return d * d; 
    } 
} 
+0

Вы начали программу под отладчиком (F5)? В этом случае оптимизация была подавлена. – usr

+1

Вы запускали сгенерированный файл .exe или внутри VS в режиме выпуска? Кроме того, вы пробовали называть их в разных заказах? Я нашел, что это делает тонкую разницу. – DGibbs

+0

Ну, почему использование int ** как двойного ** быстрее, чем просто использование двойника? – Vercas

ответ

50

Ваш тест неправильно. Во второй части вы используете int d вместо двойного. Возможно, это объясняет разницу во времени.

+0

Хорошо заметили !!! – DGibbs

+0

Время работы функции один всегда медленнее, чем встроенный на моем компьютере (неважно, int или double). – iamsleepy

+0

Абсолютно верно. Я был слепым. Вы решили это! Благодаря! – Knasterbax

22

Как правильно заметил Xavier, вы используете двойной в одном цикле и int в другом. Изменение одного и того же типа сделает результаты одинаковыми - я проверил его.

Кроме того: то, что вы на самом деле измеряете здесь, - это продолжительность дополнений и сравнений. Вы не, измеряя продолжительность квадрата d, потому что его просто не происходит: в сборке релиза оптимизатор полностью удаляет тело цикла, потому что результат не используется. Вы можете подтвердить это, комментируя тело цикла. Продолжительность будет одинаковой.

+0

Также совершенно правильно. Это была моя ошибка. Я наблюдал за int – Knasterbax

3

Даниэль Хильгарт прав, расчет не происходит вообще, поскольку результат не используется (что, вероятно, не так в режиме отладки). Попробуйте следующий пример, и вы получите правильные результаты:

static void Main(string[] args) 
    { 
     Console.WriteLine("Starting Test"); 
     var list = new List<int>(); 
     // 1. Calculating inline without function call 
     Stopwatch sw = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      int res = d * d; 
      list.Add(res); 
     } 

     sw.Stop(); 
     Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); 
     // 2. Calulating power with function call 

     list = new List<int>(); 
     Stopwatch sw2 = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      int res = Power(d); 
      list.Add(res); 
     } 

     sw2.Stop(); 
     Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); 

     Console.ReadKey(); 
    } 
+2

Не будет ли этот код вызывать 'OverflowException', так как' res' в конечном итоге будет проходить через 'Int32.MaxValue' в этих циклах? – Drewman

Смежные вопросы