Questo è un tipo di confronto delle prestazioni strano dal momento che in genere si misura il tempo necessario per calcolare qualcosa di sostanziale, piuttosto che vedere quante banali iterazioni si possono fare in un determinato periodo di tempo. Ho avuto problemi a far funzionare i tuoi codici Python e Julia, quindi ho modificato il codice Julia per funzionare e non ho eseguito il codice Python. Come notato da @chepner in un commento, l'uso now()
e il confronto dei tempi con gli DateTime
oggetti è piuttosto costoso. La time.time()
funzione Python restituisce solo un valore in virgola mobile. A quanto pare, c'è una funzione Julia chiamata time()
che fa esattamente la stessa cosa:
julia> time()
1.587648091474481e9
Ecco i tempi della tua f()
funzione originale (modificata per funzionare) sul mio 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
Ha fatto quasi 5 milioni di iterazioni prima dello scadere del tempo. Come ho detto, non sono stato in grado di ottenere il tuo codice Python per essere eseguito sul mio sistema senza una significativa manipolazione (cosa che non mi sono preoccupato di fare). Ma ecco una versione f()
che utilizza time()
invece, che chiamerò immaginativamente 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
Questa versione ha fatto 36 milioni di iterazioni. Quindi immagino che Julia sia più veloce nel looping? Sìì! Bene, in realtà il lavoro principale in questo ciclo sono le chiamate a time()
così ... Julia è più veloce nel generare molte time()
chiamate!
Perché è strano cronometrare questo? Come ho detto, la maggior parte del lavoro reale qui sta chiamando time()
. Il resto del ciclo non fa davvero nulla. In un linguaggio compilato ottimizzante, se il compilatore vede un ciclo che non fa nulla, lo eliminerà del tutto. Per esempio:
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, zero secondi! Come è possibile? Bene, diamo un'occhiata al codice LLVM (tipo di codice macchina simile ma per una macchina immaginaria che viene utilizzata come rappresentazione intermedia) questo si riduce a:
julia> @code_llvm h()
; @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
; @ REPL[16]:6 within `h'
ret i64 5000000050000000
}
Il compilatore vede il ciclo, scopre che il risultato è lo stesso ogni volta e restituisce quel valore costante invece di eseguire effettivamente il ciclo. Che, ovviamente, richiede zero tempo.