Perbandingan kecepatan Python vs Julia

9

Saya mencoba membandingkan dua cuplikan ini dan melihat berapa banyak iterasi yang dapat dilakukan dalam satu detik. Ternyata Julia mencapai 2,5 juta iterasi sedangkan Python 4 juta. Bukankah seharusnya Julia lebih cepat. Atau mungkin kedua cuplikan ini tidak setara?

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
sumber
4
Saya tidak yakin bagaimana Julia bekerja, tetapi tampaknya Anda harus membuat objek baru untuk setiap perbandingan, sementara Python melakukan perbandingan integer sederhana.
chepner
1
Juga harap dicatat bahwa ini adalah semacam perbandingan kecepatan orang miskin, bukan? Saat ini Anda dapat membuat Python dan Julia berjalan secara kasar pada kecepatan yang sama dengan jumlah motivasi yang tepat (di kedua ujungnya). Jika Anda melakukan ini untuk mengambil salah satu bahasa, lihat yang mana yang lebih mudah untuk Anda pikirkan. Anda dapat mengoptimalkannya nanti, saat Anda benar-benar membutuhkannya.
norok2
@ norok2 Itu benar untuk beberapa kode tetapi tidak untuk yang lain. Jika Anda dapat mengubah kode Python menjadi panggilan ke fungsi perpustakaan yang ditulis dalam bahasa cepat, atau jika didukung oleh numba, atau sesuatu yang serupa, maka mungkin, tetapi sebaliknya Python secara signifikan lebih lambat.
DNF
@DNF Ada beberapa hal di mana Python lebih cepat dan beberapa lainnya di mana Julia lebih cepat. Saya yakin Anda dapat menemukan contoh keduanya. Sangat mengabaikan gambar lengkap untuk mengatakan bahwa Python "secara signifikan" (apa pun artinya) lebih lambat hanya karena perulangan eksplisit dan panggilan fungsi yang relatif mahal. Tentu saja, jika itu adalah pekerjaan Anda-kuda dari mungkin Anda lebih baik dengan Julia. Namun, jika Anda menggunakan alat yang tepat, Anda bisa mendapatkan yang sama cepatnya dengan Python. Apakah perlu mempelajari alat-alat ini atau lebih baik belajar bahasa yang berbeda. Sulit dikatakan.
norok2
1
Saya menggunakan kedua bahasa tersebut, dan meskipun ada beberapa 'contoh' dari keduanya yang lebih cepat, keseimbangannya jauh di satu sisi. Ini hanyalah konsekuensi dari Python yang ditafsirkan dan hampir tidak berfokus pada kinerja sama sekali, sementara Julia memiliki fokus yang kuat pada kinerja. Sebenarnya banyak seperti mengatakan bahwa Python secepat C. Akan sangat aneh jika tidak ada perbedaan yang signifikan, dan itu akan merusak banyak tujuan Julia.
DNF

Jawaban:

9

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 DateTimeobjek 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.

StefanKarpinski
sumber
Ini adalah BogoMips dari bahasa pemrograman
norok2
1
Benar, tetapi bogomips digunakan untuk mengukur CPU, bukan bahasa pemrograman. Tapi tentu saja, itu hal yang bisa diukur.
StefanKarpinski
4

Anda mungkin ingin menggunakan time_nsfungsi di Julia:

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

Di komputer saya ini berjalan 10x lebih cepat dari Python.

Bogumił Kamiński
sumber
4

Yah, bukan itu yang saya amati di sistem saya:

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

tetapi perhatikan bahwa hanya menggunakan time(yaitu membandingkan angka biasa) masih lebih cepat:

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
sumber
tidakkah Anda seharusnya menggunakan time.perf_counter_ns()Python?
norok2
Menggunakan time.perf_counter_ns tidak mengubah apa pun (setidaknya pada sistem saya) untuk tolok ukur ini. Saya kira, ketika mengukur perbedaan waktu dalam urutan 1 detik, keakuratan pengukuran waktu tidak terlalu menjadi masalah. Hanya waktu yang diperlukan untuk melakukan pengukuran dan membandingkan benda-benda yang dihasilkan menjadi penting di sini (juga efisiensi putaran itu sendiri).
François Févotte
Dalam hal pengukuran waktu Julia - itu sebabnya dalam kode saya saya menggunakan time_nstidak timeseperti ~ ~ 30% lebih cepat.
Bogumił Kamiński