PyPy - Bagaimana mungkin mengalahkan CPython?

264

Dari Blog Google Open Source :

PyPy adalah implementasi ulang Python di Python, menggunakan teknik-teknik canggih untuk mencoba mencapai kinerja yang lebih baik daripada CPython. Kerja keras bertahun-tahun akhirnya membuahkan hasil. Hasil kecepatan kami sering mengalahkan CPython, mulai dari yang sedikit lebih lambat, hingga peningkatan hingga 2x pada kode aplikasi nyata, hingga peningkatan hingga 10x pada tolok ukur kecil.

Bagaimana ini mungkin? Implementasi Python mana yang digunakan untuk mengimplementasikan PyPy? CPython ? Dan apa peluang seorang PyPyPy atau PyPyPyPy mengalahkan skor mereka?

(Pada catatan terkait ... mengapa ada orang yang mencoba sesuatu seperti ini?)

Agnel Kurian
sumber
43
Nitpick: PyPy adalah PyPyPy. Pikirkan awalan Py * * sebagai operator proyeksi.
u0b34a0f6ae
Baik. jadi PyPy harus lebih disukai daripada CPython? apakah ada kekurangannya?
balki
10
PyPy sangat baik pada optimasi runtime, tetapi jeroan yang berbeda membuatnya tidak kompatibel dengan beberapa ekstensi C populer.
Cees Timmerman
4
Hampir setiap orang melewatkan pertanyaan, seperti bagaimana peningkatan kecepatan secara TEORI mungkin terjadi. Tetapi pikirkan: Python dapat melakukan apa saja, seperti mesin Turing. Lagipula itu bisa memanggil gcc. Jadi, Anda juga dapat menulis beberapa kode python yang berjalan di CPython, yang menginterpretasikan beberapa kode python lainnya, menerjemahkannya ke C, dan mengeksekusi gcc, dan kemudian mengeksekusi program yang dikompilasi. Dan itu bisa lebih cepat, jika kodenya disebut cukup sering.
Osa

Jawaban:

155

Q1. Bagaimana ini mungkin?

Manajemen memori manual (yang dilakukan CPython dalam penghitungannya) dapat lebih lambat daripada manajemen otomatis dalam beberapa kasus.

Keterbatasan dalam implementasi juru bahasa CPython menghalangi optimisasi tertentu yang dapat dilakukan PyPy (mis. Kunci berbutir halus).

Seperti yang disebutkan Marcelo, JIT. Mampu on the fly mengkonfirmasi jenis objek dapat menghemat kebutuhan Anda untuk melakukan beberapa pointer pointer untuk akhirnya tiba pada metode yang ingin Anda panggil.

Q2. Implementasi Python mana yang digunakan untuk mengimplementasikan PyPy?

Penerjemah PyPy diimplementasikan dalam RPython yang merupakan himpunan bagian dari Python yang diketik secara statis (bahasa dan bukan penerjemah CPython). - Rujuk https://pypy.readthedocs.org/en/latest/architecture.html untuk detailnya.

Q3. Dan apa peluang seorang PyPyPy atau PyPyPyPy mengalahkan skor mereka?

Itu akan tergantung pada implementasi dari penafsir hipotetis ini. Jika salah satu dari mereka, misalnya, mengambil sumbernya, melakukan semacam analisis terhadapnya dan mengkonversinya secara langsung menjadi kode perakitan khusus target yang ketat setelah berjalan untuk sementara waktu, saya membayangkan itu akan lebih cepat daripada CPython.

Pembaruan: Baru-baru ini, pada contoh yang dibuat dengan hati - hati , PyPy mengungguli program C serupa yang dikompilasi gcc -O3. Ini adalah kasus yang dibuat-buat tetapi menunjukkan beberapa ide.

Q4. Mengapa ada orang yang mencoba sesuatu seperti ini?

Dari situs resmi. https://pypy.readthedocs.org/en/latest/architecture.html#mission-statement

Kami bertujuan untuk menyediakan:

  • terjemahan umum dan kerangka kerja dukungan untuk menghasilkan
    implementasi bahasa dinamis, menekankan
    pemisahan yang bersih antara spesifikasi bahasa dan
    aspek implementasi . Kami menyebutnya RPython toolchain_.

  • implementasi yang sesuai, fleksibel dan cepat dari Bahasa Python_ yang menggunakan toolchain di atas untuk mengaktifkan fitur tingkat tinggi lanjutan baru tanpa harus menyandikan detail tingkat rendah.

Dengan memisahkan masalah dengan cara ini, implementasi Python kami - dan bahasa dinamis lainnya - dapat secara otomatis menghasilkan kompilator Just-in-Time untuk bahasa dinamis apa pun. Ini juga memungkinkan pendekatan campuran-dan-cocok untuk keputusan implementasi, termasuk banyak yang secara historis berada di luar kendali pengguna, seperti platform target, memori dan model threading, strategi pengumpulan sampah, dan optimisasi yang diterapkan, termasuk apakah memiliki atau tidak memiliki JIT di tempat pertama.

C compiler gcc diimplementasikan dalam C, GHK compiler Haskell ditulis dalam Haskell. Apakah Anda punya alasan mengapa juru bahasa / kompiler Python tidak ditulis dalam Python?

Noufal Ibrahim
sumber
82
Jawaban ini sama sekali tidak memiliki penjelasan utama tentang seberapa cepat PyPy; sementara itu menyebutkan bahwa PyPy tidak benar-benar diimplementasikan dalam Python, tetapi dalam RPython, itu tidak menunjukkan bahwa kode RPython secara statis dikompilasi dan dioptimalkan untuk menghasilkan interpreter PyPy (kebetulan juga kode Python yang valid yang dapat berjalan di atas dari CPython jauh lebih lambat). Apa yang telah mereka terapkan dalam "normal Python" adalah "kompiler" RPython (kerangka terjemahan yang dimaksud dalam kutipan blok).
Ben
12
Ini mengubur lede. Sebagian besar kinerja berasal dari terjemahan ke C (yang membuat penerjemah tidak lebih lambat dari CPython), dan JIT, yang membuat jalur panas lebih cepat.
Tobu
4
"Pembaruan: Baru-baru ini, pada contoh yang dibuat dengan hati-hati, PyPy mengungguli program C serupa yang dikompilasi dengan gcc -O3." Dan jika Anda membaca komentar pertama di bawah postingan itu, Anda akan melihat bahwa penulis postingan itu tidak mengetahui optimasi tautan-waktu. Dengan optimasi tautan-waktu diaktifkan, kode C berjalan lebih cepat.
Ali
2
Yah, postingan blog itu pada 2011 dan jawaban ini pada 2014. Juga, komentar itu menyebutkan perpustakaan bersama. Saya tidak tahu berapa banyak dari ini (jawaban dan posting blog) valid. Semua teknologi yang terlibat telah banyak berubah dalam beberapa tahun terakhir.
Noufal Ibrahim
1
Pada dua contoh Pypy yang dibuat dengan hati-hati lebih cepat daripada C yang setara, masing-masing lebih cepat dalam patokan untuk serangkaian alasan yang sangat spesifik. Yang pertama karena Pypy cukup pintar untuk menyadari hal-hal penghitungan loop ketat tidak pernah memiliki jumlah yang digunakan, sehingga dapat dihapus seluruhnya (JIT pass) yang kedua untuk kombinasi dari: karena Pypy JIT dapat "sejajar melintasi batas perpustakaan", mengingat contoh fungsi "printf" yang dikhususkan untuk secara harfiah hanya dapat memancarkan bilangan bulat, dan menghilangkan malloc berulang (overhead alokasi memori).
amcgregor
291

"PyPy adalah implementasi ulang Python dengan Python" adalah cara yang agak menyesatkan untuk menggambarkan PyPy, IMHO, meskipun secara teknis itu benar.

Ada dua bagian utama PyPy.

  1. Kerangka terjemahan
  2. Penerjemah

Kerangka terjemahan adalah kompiler. Itu mengkompilasi kode RPython ke C (atau target lainnya), secara otomatis menambahkan dalam aspek-aspek seperti pengumpulan sampah dan kompiler JIT. Itu tidak dapat menangani kode Python sewenang-wenang, hanya RPython.

RPython adalah bagian dari Python normal; semua kode RPython adalah kode Python, tetapi tidak sebaliknya. Tidak ada definisi formal dari RPython, karena RPython pada dasarnya hanyalah "himpunan bagian dari Python yang dapat diterjemahkan oleh kerangka kerja terjemahan Pypy". Tetapi untuk diterjemahkan, kode RPython harus diketik secara statis (jenisnya disimpulkan, Anda tidak mendeklarasikannya, tetapi masih satu jenis per variabel), dan Anda tidak dapat melakukan hal-hal seperti mendeklarasikan / memodifikasi fungsi / kelas saat runtime juga.

Penerjemah kemudian adalah juru bahasa Python normal yang ditulis dalam RPython.

Karena kode RPython adalah kode Python normal, Anda dapat menjalankannya pada penerjemah Python apa pun. Tapi tidak ada klaim kecepatan PyPy yang datang dari menjalankannya seperti itu; ini hanya untuk siklus tes cepat, karena menerjemahkan penerjemah membutuhkan waktu lama .

Dengan memahami itu, harus segera jelas bahwa spekulasi tentang PyPyPy atau PyPyPyPy sebenarnya tidak masuk akal. Anda memiliki juru bahasa yang ditulis dalam RPython. Anda menerjemahkannya ke kode C yang mengeksekusi Python dengan cepat. Di sana proses berhenti; tidak ada lagi RPython untuk mempercepat dengan memprosesnya lagi.

Jadi "Bagaimana mungkin PyPy lebih cepat dari CPython" juga menjadi cukup jelas. PyPy memiliki implementasi yang lebih baik, termasuk kompiler JIT (umumnya tidak secepat tanpa kompiler JIT, saya percaya, yang berarti PyPy hanya lebih cepat untuk program yang rentan terhadap kompilasi JIT). CPython tidak pernah dirancang untuk menjadi implementasi yang sangat optimal dari bahasa Python (meskipun mereka mencoba membuatnya menjadi implementasi yang sangat optimal , jika Anda mengikuti perbedaannya).


Bagian proyek PyPy yang benar-benar inovatif adalah bahwa mereka tidak menulis skema GC canggih atau kompiler JIT dengan tangan. Mereka menulis interpreter relatif mudah dalam RPython, dan untuk semua RPython adalah tingkat yang lebih rendah daripada Python itu masih merupakan bahasa pengumpulan sampah berorientasi objek, tingkat yang jauh lebih tinggi daripada C. Kemudian kerangka terjemahan secara otomatis menambahkan hal-hal seperti GC dan JIT. Jadi kerangka terjemahannya sangat besarupaya, tetapi itu berlaku sama baiknya untuk juru bahasa python PyPy namun mereka mengubah implementasi mereka, memungkinkan untuk lebih banyak kebebasan dalam percobaan untuk meningkatkan kinerja (tanpa khawatir tentang memperkenalkan bug GC atau memperbarui kompiler JIT untuk mengatasi perubahan). Ini juga berarti ketika mereka berusaha menerapkan juru bahasa Python3, itu akan secara otomatis mendapatkan manfaat yang sama. Dan penterjemah lain yang ditulis dengan kerangka PyPy (yang ada sejumlah pada berbagai tahap polandia). Dan semua penerjemah yang menggunakan kerangka PyPy secara otomatis mendukung semua platform yang didukung oleh kerangka tersebut.

Jadi manfaat sebenarnya dari proyek PyPy adalah memisahkan (sebanyak mungkin) semua bagian dari penerapan juru bahasa independen platform yang efisien untuk bahasa yang dinamis. Dan kemudian muncul dengan satu implementasi yang baik dari mereka di satu tempat, yang dapat digunakan kembali di banyak penerjemah. Itu bukan kemenangan langsung seperti "program Python saya berjalan lebih cepat sekarang", tapi ini prospek yang bagus untuk masa depan.

Dan itu dapat menjalankan program Python Anda lebih cepat (mungkin).

Ben
sumber
4
Saya tidak bisa mengikuti perbedaan :(
polvoazul
37
@polvoazul Perbedaan antara implementasi bahasa yang dioptimalkan dan yang optimal ? Nah, ketika saya mengatakan CPython adalah implementasi yang dioptimalkan dengan baik, maksud saya bahwa pengembang mencoba membuat algoritma internal dari interpreter itu sendiri dan struktur data builtin berjalan secara efisien. Sebuah mengoptimalkan pelaksanaan, Otoh, akan menganalisis pengguna akhir kode dan mencoba untuk mencari tahu cara untuk mengubahnya untuk mengeksekusi lebih efisien.
Ben
23

PyPy diimplementasikan dalam Python, tetapi mengimplementasikan kompiler JIT untuk menghasilkan kode asli dengan cepat.

Alasan untuk mengimplementasikan PyPy di ​​atas Python mungkin adalah itu hanya bahasa yang sangat produktif, terutama karena kompiler JIT membuat kinerja bahasa host agak tidak relevan.

Marcelo Cantos
sumber
Apakah JIT menghasilkan kode Python berjalan pada tingkat yang sama dengan PyPy, atau apakah itu menghasilkan kode asli nyata berjalan pada tingkat di mana implementasi Python implementasi PyPy berjalan?
Edmund
3
Kode asli asli (lihat di sini ); Kode x86 32-bit tepatnya.
Marcelo Cantos
11

PyPy ditulis dalam Python Terbatas. Itu tidak berjalan di atas juru bahasa CPython, sejauh yang saya tahu. Python terbatas adalah bagian dari bahasa Python. AFAIK, interpreter PyPy dikompilasi ke kode mesin, jadi ketika diinstal tidak menggunakan interpreter python saat runtime.

Pertanyaan Anda tampaknya mengharapkan interpreter PyPy berjalan di atas CPython saat menjalankan kode. Sunting: Ya, untuk menggunakan PyPy Anda pertama-tama menerjemahkan kode python PyPy, baik ke C dan membangun dengan gcc, ke kode byte jvm, atau ke kode .Net CLI. Lihat Memulai

bobpaul
sumber
8
PyPy akan berjalan di atas CPython tetapi dalam mode ini tidak memberikan kecepatan yang diinginkan seseorang. :-) codespeak.net/pypy/dist/pypy/doc/…
Frank V