Python Сравнение скорости с Юлией - PullRequest
9 голосов
/ 23 апреля 2020

Я попытался сравнить эти два фрагмента и посмотреть, сколько итераций можно выполнить за одну секунду. Оказывается, Юлия достигает 2,5 миллиона итераций, тогда как Python 4 миллиона. Разве Джулия не должна быть быстрее? Или, может быть, эти два фрагмента не эквивалентны?

Python:

t1 = time.time()
i = 0
while True:
    i += 1
    if time.time() - t1 >= 1:
        break

Юлия:

function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end

Ответы [ 3 ]

9 голосов
/ 23 апреля 2020

Это своего рода странное сравнение производительности, поскольку обычно измеряется время, необходимое для вычисления чего-то существенного, вместо того, чтобы видеть, сколько тривиальных итераций можно выполнить за определенное время. У меня были проблемы с тем, чтобы заставить работать ваши Python и коды Julia, поэтому я модифицировал код Julia для работы и просто не запустил код Python. Как отметил @chepner в комментарии, использование now() и сравнение времени с DateTime объектами довольно дорого. Функция Python time.time() просто возвращает значение с плавающей точкой. Как выяснилось, есть функция Julia с именем time(), которая делает то же самое:

julia> time()
1.587648091474481e9

Вот время вашей исходной функции f() (измененной для работы) в моей системе:

julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
4943739

Он сделал почти 5 миллионов итераций, прежде чем время истекло. Как я уже сказал, я не смог заставить ваш Python код работать в моей системе без особых хлопот (что я и не удосужился сделать). Но вот версия f(), в которой вместо этого используется time(), которую я наглядно назову g():

julia> function g()
           i = 0
           t1 = time()
           while true
               i += 1
               if time() - t1 >= 1
                   break
               end
           end
           return i
       end
g (generic function with 1 method)

julia> g()
36087637

Эта версия сделала 36 миллионов итераций. Значит, Джулия быстрее зацикливается? Ура! Ну, на самом деле основная работа в этом l oop - это звонки на time(), так что ... Джулия быстрее генерирует множество time() звонков!

Почему это странное время? Как я уже сказал, большая часть реальной работы здесь называется time(). Остальная часть l oop ничего не делает. В оптимизируемом скомпилированном языке, если компилятор видит, что oop ничего не делает, он полностью его устраняет. Например:

julia> function h()
           t = 0
           for i = 1:100_000_000
               t += i
           end
           return t
       end
h (generic function with 1 method)

julia> h()
5000000050000000

julia> @time h()
  0.000000 seconds
5000000050000000    

Вау, ноль секунд! Как это возможно? Хорошо, давайте посмотрим на LLVM-код (вроде машинного кода, но для воображаемой машины, которая используется в качестве промежуточного представления), это понижается до:

julia> @code_llvm h()

;  @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
;  @ REPL[16]:6 within `h'
  ret i64 5000000050000000
}

Компилятор видит l oop, выясняет, что результат всегда один и тот же, и просто возвращает это постоянное значение вместо фактического выполнения l oop. Что, конечно, занимает ноль времени.

4 голосов
/ 23 апреля 2020

Ну, это не то, что я наблюдаю в моей системе:

Python 3.7.7

Python 3.7.7 (default, Mar 26 2020, 15:48:22) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import time                                                                                                                                                       

In [2]: def f(): 
   ...:     t1 = time.time() 
   ...:     i = 0 
   ...:     while True: 
   ...:         i += 1 
   ...:         if time.time() - t1 >= 1: 
   ...:             return i 
   ...:                                                                                                                                                                   

In [3]: f()                                                                                                                                                               
Out[3]: 4676268

Юлия 1.4.0:

julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Dates.Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
6339528

но обратите внимание, что простое использование time (то есть сравнение простых чисел) все еще быстрее:

julia> function f()
           i = 0
           t1 = time()
           while true
               i += 1
               if time() - t1 >= 1
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
24742703

4 голосов
/ 23 апреля 2020

Возможно, вы хотите использовать функцию time_ns в Юлии:

function f()
    i = 0
    t1 = time_ns()
    while true
        i += 1
        if time_ns() - t1 >= 10^9
            break
        end
    end
    return i
end

На моем компьютере она работает в 10 раз быстрее, чем Python.

...