2015-01-02 5 views
1

Рассмотрим следующий фрагмент кода (Julia)Производительность первого против второго вызова функции

bar(x) = for i = 1:9999 x+x*x-x+x end # Define the "bar" function 
print("First try: "); @time bar(0.5) 
print("Second try: "); @time bar(0.5) 
bar(x) = for i = 1:9999 x+x*x-x+x end # Redefine the same "bar" function 
print("Third try: "); @time bar(0.5) 
print("Fourth try: "); @time bar(0.6) 

Выход

First try: elapsed time: 0.002738996 seconds (88152 bytes allocated) 
Second try: elapsed time: 3.827e-6 seconds (80 bytes allocated) 
Third try: elapsed time: 0.002907554 seconds (88152 bytes allocated) 
Fourth try: elapsed time: 2.395e-6 seconds (80 bytes allocated) 

Почему второй (и четвертый) попробовать так гораздо быстрее (и занимают меньше памяти), чем первая (и третья) попытка?

+1

У Джулии есть, я понимаю, компилятор точно в срок. Таким образом, первый (и третий) запуск - это компиляция кода (с необходимыми для этого выделениями), а во втором (и четвертом) запусках выполняется только скомпилированный ранее код. –

+0

Вне темы: что произойдет, если вы повторно запустите код, не изменяя его? Python создает файлы .pyc (вид скомпилированного исходного кода). Если файлы pyc по-прежнему соответствуют исходному файлу, ему не придется снова перекомпилировать его (ну, не все снова). => быстрее –

+0

О, хорошо. Это имеет смысл. Я бы подумал, что компиляция произойдет при определении функции, а не в первый раз для запуска. Я думаю, вы можете сделать ответ из своего комментария. Спасибо @Paul –

ответ

3

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

3

Просто для того, чтобы расширить ответ Павла: большая часть ускорение происходит от вывода типа Юлии и множественной отправки. Скажем, первый раз, когда вы оцениваете функцию с помощью float: JIT (только во время компилятора) вычисляет тип аргумента и записывает соответствующий код LLVM. Если вы затем оцениваете одну и ту же функцию с целым числом, это компилирует другой код LLVM. В следующий раз, когда вы вызываете функцию, она будет отправлять разные коды LLVM в зависимости от типа аргумента. Именно по этой причине было бы нецелесообразно компилировать, когда вы определяете функцию.

Вы можете прочитать больше об этом here, например (есть тонны ссылок на многократной отправки в документации!)

Рассмотрим, например:

bar(x) = for i = 1:9999 x+x*x-x+x end 

print("First try with floats: "); @time bar(0.5) 
print("Second try with floats: "); @time bar(0.5) 

print("First try with integers: "); @time bar(1) 
print("Second try with integers: "); @time bar(1) 

, который дает:

First try with floats: elapsed time: 0.005570773 seconds (102440 bytes allocated) 
Second try with floats: elapsed time: 5.762e-6 seconds (80 bytes allocated)  
First try with integers: elapsed time: 0.003584026 seconds (86896 bytes allocated)  
Second try with integers: elapsed time: 6.402e-6 seconds (80 bytes allocated) 

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

  • Нет связанных вопросов^_^