Comparación de velocidad Python vs Julia

9

Traté de comparar estos dos fragmentos y ver cuántas iteraciones se podían hacer en un segundo. Resulta que Julia logra 2.5 millones de iteraciones mientras que Python 4 millones. ¿No se supone que Julia sea más rápida? ¿O tal vez estos dos fragmentos no son equivalentes?

Pitón:

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

Julia

function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end
Michas
fuente
44
No estoy seguro de cómo funciona Julia, pero parece que tienes que construir un nuevo objeto para cada comparación, mientras que Python está haciendo comparaciones enteras simples.
chepner
1
También tenga en cuenta que esta es una especie de comparación de la velocidad del hombre pobre, ¿no? Hoy en día puedes hacer que Python y Julia corran aproximadamente a la misma velocidad con la cantidad adecuada de motivación (en ambos extremos). Si está haciendo esto para aprender cualquiera de los idiomas, busque en cuál es más fácil pensar. Puede optimizar eso más tarde, cuando realmente lo necesite.
norok2
@ norok2 Eso es cierto para algunos códigos pero no para otros. Si puede convertir el código de Python en una llamada a una función de biblioteca escrita en un lenguaje rápido, o si es compatible con numba o algo similar, entonces tal vez, pero de lo contrario, Python es significativamente más lento.
DNF
@DNF Hay algunas cosas donde Python es más rápido y otras donde Julia es más rápida. Estoy seguro de que puedes encontrar ejemplos de ambos. Es ignorar excesivamente la imagen completa decir que Python es "significativamente" (lo que sea que eso signifique) más lento solo debido a las llamadas a funciones y bucles explícitos relativamente caros. Claro, si ese es tu caballo de trabajo, entonces quizás estés mejor con Julia. Sin embargo, si usa las herramientas adecuadas, puede obtener la misma rapidez en Python. ¿Vale la pena aprender estas herramientas o es mejor aprender un idioma diferente? Es difícil de decir.
norok2
1
Utilizo ambos idiomas, y aunque hay "algunos" ejemplos de que ambos son más rápidos, el equilibrio es considerablemente considerable. Es simplemente una consecuencia de que Python sea interpretado y apenas se centre en el rendimiento, mientras que Julia tiene un fuerte enfoque en el rendimiento. En realidad, es muy parecido a decir que Python es tan rápido como C. Sería muy extraño si no hubiera una diferencia significativa, y socavaría gran parte del propósito de Julia.
DNF

Respuestas:

9

Esta es una especie de comparación de rendimiento extraño, ya que normalmente se mide el tiempo que lleva calcular algo sustancial, en lugar de ver cuántas iteraciones triviales se pueden hacer en una cierta cantidad de tiempo. Tuve problemas para que sus códigos Python y Julia funcionen, así que modifiqué el código Julia para que funcione y simplemente no ejecuté el código Python. Como señaló @chepner en un comentario, usar now()y hacer comparaciones de tiempo con DateTimeobjetos es bastante costoso. La time.time()función Python solo devuelve un valor de punto flotante. Como resultado, hay una función llamada Julia time()que hace exactamente lo mismo:

julia> time()
1.587648091474481e9

Aquí está el momento de su f()función original (modificada para trabajar) en mi sistema:

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

Hizo casi 5 millones de iteraciones antes de que se agotara el tiempo. Como dije, no pude hacer que tu código de Python se ejecutara en mi sistema sin una manipulación significativa (lo cual no me molesté en hacer). Pero aquí hay una versión de f()esos usos time(), que llamaré imaginativamente 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

Esta versión hizo 36 millones de iteraciones. ¿Entonces supongo que Julia es más rápida en el looping? ¡Hurra! Bueno, en realidad el trabajo principal en este bucle son las llamadas a time()... Julia es más rápida en generar muchas time()llamadas.

¿Por qué es extraño cronometrar esto? Como dije, la mayor parte del trabajo real aquí está llamando time(). El resto del ciclo realmente no hace nada. En un lenguaje compilado optimizado, si el compilador ve un ciclo que no hace nada, lo eliminará por completo. Por ejemplo:

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    

Woah, cero segundos! ¿Cómo es eso posible? Bueno, echemos un vistazo al código LLVM (algo así como un código de máquina, pero para una máquina imaginaria que se usa como una representación intermedia), esto se reduce a:

julia> @code_llvm h()

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

El compilador ve el ciclo, descubre que el resultado es el mismo cada vez y simplemente devuelve ese valor constante en lugar de ejecutar el ciclo. Lo cual, por supuesto, lleva cero tiempo.

StefanKarpinski
fuente
Son los BogoMips de los lenguajes de programación
norok2
1
Correcto, pero los bogomips se usan para medir la CPU, no el lenguaje de programación. Pero claro, es algo que uno puede medir.
StefanKarpinski
4

Probablemente quieras usar la time_nsfunción en Julia:

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

En mi computadora funciona 10 veces más rápido que Python.

Bogumił Kamiński
fuente
4

Bueno, eso no es lo que observo en mi sistema:

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


Julia 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

pero tenga en cuenta que simplemente usar time(es decir, comparar números simples) es aún más rápido:

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
François Févotte
fuente
¿No deberías usar time.perf_counter_ns()en Python?
norok2
Usar time.perf_counter_ns no cambia nada (al menos en mi sistema) para este punto de referencia. Supongo que, al medir las diferencias de tiempo en el orden de 1 segundo, la precisión de la medición del tiempo no importa mucho. Aquí solo importa el tiempo necesario para realizar la medición y comparar los objetos resultantes (así como la eficiencia de los propios bucles).
François Févotte
En materia de tiempo de medición Julia - es por eso que en mi código utilicé time_nsno time, ya que es ~ 30% más rápido entonces.
Bogumił Kamiński