Python vs Julia Geschwindigkeitsvergleich

9

Ich habe versucht, diese beiden Schnipsel zu vergleichen und zu sehen, wie viele Iterationen in einer Sekunde durchgeführt werden können. Es stellt sich heraus, dass Julia 2,5 Millionen Iterationen erreicht, Python 4 Millionen. Soll Julia nicht schneller sein? Oder sind diese beiden Schnipsel vielleicht nicht gleichwertig?

Python:

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
quelle
4
Ich bin nicht sicher, wie Julia funktioniert, aber es scheint, dass Sie für jeden Vergleich ein neues Objekt erstellen müssen, während Python einfache Ganzzahlvergleiche durchführt.
Chepner
1
Bitte beachten Sie auch, dass dies ein Vergleich der Geschwindigkeit eines armen Mannes ist, nicht wahr? Heutzutage können Sie Python und Julia mit der richtigen Motivation (an beiden Enden) ungefähr mit der gleichen Geschwindigkeit laufen lassen. Wenn Sie dies tun, um eine der Sprachen zu erlernen, suchen Sie nach einer, mit der Sie leichter nachdenken können. Sie können dies später optimieren, wenn Sie es tatsächlich benötigen.
norok2
@ norok2 Das gilt für einige Codes, aber nicht für andere. Wenn Sie in der Lage sind, den Python-Code in einen Aufruf einer in einer schnellen Sprache geschriebenen Bibliotheksfunktion umzuwandeln, oder wenn er von numba oder ähnlichem unterstützt wird, dann vielleicht, aber ansonsten ist Python erheblich langsamer.
DNF
@DNF Es gibt einige Dinge, bei denen Python schneller ist, und andere, bei denen Julia schneller ist. Ich bin sicher, Sie können Beispiele für beides finden. Es wird übermäßig ignoriert, das gesamte Bild zu sagen, dass Python "signifikant" (was auch immer das bedeuten mag) langsamer ist, nur wegen der relativ teuren expliziten Schleifen- und Funktionsaufrufe. Klar, wenn das dein Arbeitspferd ist, dann bist du vielleicht besser dran mit Julia. Wenn Sie jedoch die richtigen Tools verwenden, können Sie in Python genauso schnell arbeiten. Lohnt es sich, diese Werkzeuge zu lernen, oder ist es besser, eine andere Sprache zu lernen? Es ist schwer zu sagen.
norok2
1
Ich benutze beide Sprachen, und obwohl es "einige" Beispiele dafür gibt, dass beide schneller sind, ist das Gleichgewicht auf einer Seite erheblich. Es ist einfach eine Folge davon, dass Python interpretiert wird und sich kaum auf Leistung konzentriert, während Julia einen starken Fokus auf Leistung hat. Es ist eigentlich sehr ähnlich zu sagen, dass Python so schnell wie C ist. Es wäre sehr seltsam, wenn es keinen signifikanten Unterschied gäbe, und es würde einen Großteil des Zwecks von Julia untergraben.
DNF

Antworten:

9

Dies ist eine Art seltsamer Leistungsvergleich, da man normalerweise die Zeit misst, die benötigt wird, um etwas Substanzielles zu berechnen, anstatt zu sehen, wie viele triviale Iterationen man in einer bestimmten Zeit durchführen kann. Ich hatte Probleme, Ihre Python- und Julia-Codes zum Laufen zu bringen, daher habe ich den Julia-Code so geändert, dass er funktioniert, und den Python-Code einfach nicht ausgeführt. Wie @chepner in einem Kommentar feststellte, ist die Verwendung now()und Durchführung von Zeitvergleichen mit DateTimeObjekten ziemlich teuer. Die Python- time.time()Funktion gibt nur einen Gleitkommawert zurück. Wie sich herausstellt, gibt es eine Julia-Funktion time(), die genau dasselbe tut:

julia> time()
1.587648091474481e9

Hier ist das Timing Ihrer ursprünglichen f()Funktion (geändert, um zu funktionieren) auf meinem System:

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

Es wurden fast 5 Millionen Iterationen durchgeführt, bevor die Zeit abgelaufen war. Wie gesagt, ich konnte Ihren Python-Code nicht ohne nennenswerten Aufwand auf meinem System ausführen (was ich nicht getan habe). Aber hier ist eine Version , f()dass Anwendungen time()statt, die ich einfallsreich nennen 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

Diese Version hat 36 Millionen Iterationen durchgeführt. Also denke ich, Julia ist schneller im Looping? Yay! Nun, eigentlich ist die Hauptarbeit in dieser Schleife das Anrufen von time()... Julia ist schneller darin, viele time()Anrufe zu generieren !

Warum ist es seltsam, dies zu messen? Wie gesagt, die meiste Arbeit hier ruft an time(). Der Rest der Schleife macht eigentlich nichts. Wenn der Compiler in einer optimierten kompilierten Sprache eine Schleife sieht, die nichts tut, wird sie vollständig entfernt. Zum Beispiel:

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, null Sekunden! Wie ist das möglich? Schauen wir uns das an LLVM-Code an (ähnlich wie Maschinencode, aber für eine imaginäre Maschine, die als Zwischendarstellung verwendet wird).

julia> @code_llvm h()

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

Der Compiler sieht die Schleife, stellt fest, dass das Ergebnis jedes Mal das gleiche ist, und gibt nur diesen konstanten Wert zurück, anstatt die Schleife tatsächlich auszuführen. Was natürlich keine Zeit in Anspruch nimmt.

StefanKarpinski
quelle
Es sind die BogoMips der Programmiersprachen
norok2
1
Richtig, aber Bogomips werden verwendet, um die CPU zu messen, nicht die Programmiersprache. Aber sicher, das kann man messen.
StefanKarpinski
4

Sie möchten wahrscheinlich die time_nsFunktion in Julia verwenden:

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

Auf meinem Computer läuft es 10x schneller als Python.

Bogumił Kamiński
quelle
4

Nun, das ist nicht das, was ich auf meinem System beobachte:

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

Beachten Sie jedoch, dass die einfache Verwendung time(dh der Vergleich einfacher Zahlen) immer noch schneller ist:

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
quelle
sollten Sie nicht time.perf_counter_ns()in Python verwenden?
norok2
Die Verwendung von time.perf_counter_ns ändert nichts (zumindest auf meinem System) für diesen Benchmark. Ich denke, dass bei der Messung von Zeitunterschieden in der Größenordnung von 1 Sekunde die Genauigkeit der Zeitmessung keine große Rolle spielt. Hier spielt nur die Zeit eine Rolle, die für die Messung und den Vergleich der resultierenden Objekte benötigt wird (sowie die Effizienz der Schleifen selbst).
François Févotte
In Julia zählt die Messzeit - deshalb habe ich in meinem Code time_nsnicht verwendet, timeda es dann ~ 30% schneller ist.
Bogumił Kamiński