Saya menulis skrip berikut untuk menguji kecepatan fungsi semacam Python:
from sys import stdin, stdout
lines = list(stdin)
lines.sort()
stdout.writelines(lines)
Saya kemudian membandingkan ini dengan sort
perintah coreutils pada file yang berisi 10 juta baris:
$ time python sort.py <numbers.txt >s1.txt
real 0m16.707s
user 0m16.288s
sys 0m0.420s
$ time sort <numbers.txt >s2.txt
real 0m45.141s
user 2m28.304s
sys 0m0.380s
Perintah bawaan menggunakan keempat CPU (Python hanya menggunakan satu) tetapi membutuhkan waktu sekitar 3 kali lebih lama untuk dijalankan! Apa yang menyebabkannya?
Saya menggunakan Ubuntu 12.04.5 (32-bit), Python 2.7.3, dan sort
8.13
--buffer-size
untuk menentukan yangsort
menggunakan semua memori fisik yang tersedia dan melihat apakah itu membantu?Jawaban:
Komentar Izkata mengungkapkan jawabannya: perbandingan spesifik-lokal. The
sort
perintah menggunakan lokal yang ditunjukkan oleh lingkungan, sedangkan default Python untuk perbandingan urutan byte. Membandingkan string UTF-8 lebih sulit daripada membandingkan string byte.Bagaimana tentang itu.
sumber
locale.strxfrm
untuk menyortir, skrip butuh ~ 32 detik, masih lebih cepat darisort
tetapi jauh lebih sedikit.cut
, dan yang lain juga. Pada beberapa mesin saya sekarang memilikiexport LC_ALL=C
di.bashrc
. Tetapi berhati-hatilah: ini pada dasarnya rusakwc
(kecualiwc -l
), hanya untuk memberi contoh. "Bad byte" tidak dihitung sama sekali ...grep
: Anda bisa mendapatkan peningkatan kinerja yang substansial ketika mengambil file besar dengan menonaktifkan UTF-8, terutama ketika melakukangrep -i
Ini lebih merupakan analisis tambahan daripada jawaban yang sebenarnya tetapi tampaknya bervariasi tergantung pada data yang diurutkan. Pertama, bacaan dasar:
OK, python jauh lebih cepat. Namun, Anda dapat membuat core
sort
lebih cepat dengan menyuruhnya mengurutkan secara numerik:Itu jauh lebih cepat tetapi python masih menang dengan selisih yang lebar. Sekarang, mari kita coba lagi tetapi dengan daftar nomor 1M yang tidak disortir:
Coreutils
sort -n
lebih cepat untuk data numerik yang tidak disortir (meskipun Anda mungkin dapat mengubahcmp
parameter python sort untuk membuatnya lebih cepat). Coreutilssort
masih jauh lebih lambat tanpa-n
flag. Jadi, bagaimana dengan karakter acak, bukan angka murni?Python masih mengalahkan coreutils tetapi dengan margin yang jauh lebih kecil dari apa yang Anda tunjukkan dalam pertanyaan Anda. Yang mengejutkan, ini masih lebih cepat ketika melihat data alfabet murni:
Penting juga untuk dicatat bahwa keduanya tidak menghasilkan output yang diurutkan yang sama:
Anehnya,
--buffer-size
pilihan itu tampaknya tidak membuat banyak (atau ada) perbedaan dalam tes saya. Sebagai kesimpulan, mungkin karena berbagai algoritma yang disebutkan dalam jawaban goldilock, pythonsort
tampaknya lebih cepat dalam banyak kasus tetapi GNU numeriksort
mengalahkannya pada angka 1 yang tidak disortir .OP mungkin telah menemukan akar penyebabnya tetapi demi kelengkapan, inilah perbandingan terakhir:
1 Seseorang dengan lebih banyak python-fu daripada saya harus mencoba menguji tweaking
list.sort()
untuk melihat dengan kecepatan yang sama dapat dicapai dengan menentukan metode penyortiran.sumber
sort
tampaknya melakukan sedikit pekerjaan ekstra untuk perbandingan huruf besar / kecil.stdin
input mentah . Mengubahnya menjadi angka (lines = map(int, list(stdin))
) dan kembali (stdout.writelines(map(str,lines))
) membuat penyortiran keseluruhan menjadi lebih lambat, naik dari 0,234 nyata menjadi 0,720 pada mesin saya.Kedua implementasinya ada di C, jadi level playing field di sana. Coreutils
sort
rupanya menggunakan algoritma mergesort . Mergesort melakukan sejumlah perbandingan tetap yang meningkatkan secara logaritma ke ukuran input, yaitu O besar (n log n).Penyortiran Python menggunakan penggabungan / penyisipan hibrid unik, timsort , yang akan melakukan sejumlah variabel perbandingan dengan skenario kasus terbaik O (n) - mungkin, pada daftar yang sudah disortir - tetapi umumnya logaritmik (secara logis, Anda tidak bisa lebih baik daripada logaritmik untuk kasus umum saat menyortir).
Dengan dua jenis logaritmik yang berbeda, yang satu dapat memiliki keunggulan di atas yang lain pada beberapa kumpulan data tertentu. Semacam gabungan tradisional tidak bervariasi, sehingga akan melakukan hal yang sama terlepas dari data, tetapi misalnya, quicksort (juga logaritmik), yang memang bervariasi, akan berkinerja lebih baik pada beberapa data tetapi lebih buruk pada yang lain.
Faktor tiga (atau lebih dari 3, karena
sort
diparalelkan) agak sedikit, yang membuat saya bertanya-tanya apakah tidak ada beberapa kemungkinan di sini, sepertisort
bertukar ke disk (-T
opsi tampaknya menyiratkan itu tidak). Namun, sistem rendah Anda vs waktu pengguna menyiratkan ini bukan masalah.sumber