Ini adalah semacam perbandingan kinerja yang aneh karena biasanya seseorang mengukur waktu yang diperlukan untuk menghitung sesuatu yang substansial, daripada melihat berapa banyak iterasi sepele yang dapat dilakukan seseorang dalam jumlah waktu tertentu. Saya kesulitan membuat kode Python dan Julia Anda berfungsi, jadi saya memodifikasi kode Julia agar berfungsi dan tidak menjalankan kode Python. Seperti dicatat oleh @chepner dalam komentar, menggunakan now()
dan melakukan perbandingan waktu dengan DateTime
objek cukup mahal. Fungsi Python time.time()
hanya mengembalikan nilai floating-point. Ternyata, ada fungsi Julia disebut time()
yang melakukan hal yang persis sama:
julia> time()
1.587648091474481e9
Inilah waktu f()
fungsi asli Anda (dimodifikasi untuk berfungsi) pada sistem saya:
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
Itu hampir 5 juta iterasi sebelum waktu habis. Seperti yang saya katakan, saya tidak bisa mendapatkan kode Python Anda untuk berjalan di sistem saya tanpa mengutak-atik yang signifikan (yang saya tidak repot lakukan). Tapi di sini adalah versi f()
yang menggunakan time()
, yang secara imajinatif saya sebut 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
Versi ini menghasilkan 36 juta iterasi. Jadi saya kira Julia lebih cepat di perulangan? Yay! Sebenarnya pekerjaan utama dalam loop ini adalah panggilan untuk time()
jadi ... Julia lebih cepat menghasilkan banyak time()
panggilan!
Mengapa aneh waktu ini? Seperti yang saya katakan, sebagian besar pekerjaan aktual di sini adalah menelepon time()
. Sisa loop tidak benar-benar melakukan apa pun. Dalam bahasa kompilasi yang dioptimalkan, jika kompiler melihat loop yang tidak melakukan apa-apa, itu akan menghilangkannya sama sekali. Sebagai contoh:
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, nol detik! Bagaimana mungkin? Baiklah, mari kita lihat kode LLVM (semacam kode mesin seperti tetapi untuk mesin imajiner yang digunakan sebagai representasi perantara) ini menurunkan ke:
julia> @code_llvm h()
; @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
; @ REPL[16]:6 within `h'
ret i64 5000000050000000
}
Compiler melihat loop, memperkirakan bahwa hasilnya sama setiap kali, dan hanya mengembalikan nilai konstan itu daripada benar-benar mengeksekusi loop. Yang tentu saja membutuhkan waktu nol.