Multicore Python: Sasaran yang tangguh, layak, dan dapat dicapai

Untuk semua fitur Python yang hebat dan nyaman, satu tujuan tetap tidak terjangkau: Aplikasi Python berjalan pada penerjemah referensi CPython dan menggunakan beberapa inti CPU secara paralel.

Ini telah lama menjadi salah satu batu sandungan terbesar Python, terutama karena semua penyelesaiannya kikuk. Urgensi untuk menemukan solusi jangka panjang untuk masalah ini semakin meningkat, terutama karena jumlah inti pada prosesor terus meningkat (lihat raksasa 24-inti Intel).

Satu kunci untuk semua

Sebenarnya, dimungkinkan untuk menggunakan utas dalam aplikasi Python - banyak di antaranya sudah melakukannya. Apa yang  tidak mungkin bagi CPython untuk menjalankan aplikasi multithread dengan setiap utas dijalankan secara paralel pada inti yang berbeda. Manajemen memori internal CPython tidak aman untuk thread, jadi interpreter hanya menjalankan satu thread pada satu waktu, beralih di antaranya sesuai kebutuhan dan mengontrol akses ke status global.

Mekanisme penguncian ini, Global Interpreter Lock (GIL), adalah satu-satunya alasan terbesar mengapa CPython tidak dapat menjalankan utas secara paralel. Ada beberapa faktor yang meringankan; misalnya, operasi I / O seperti pembacaan disk atau jaringan tidak terikat oleh GIL, sehingga dapat berjalan dengan bebas di utasnya sendiri. Tapi apa pun yang multithread dan terikat dengan CPU adalah masalah.

Untuk programmer Python, ini berarti tugas komputasi berat yang diuntungkan karena tersebar di beberapa core tidak berjalan dengan baik, kecuali penggunaan library eksternal. Kenyamanan bekerja dengan Python datang dengan biaya kinerja yang besar, yang menjadi lebih sulit untuk diterima karena lebih cepat, bahasa yang sama nyamannya seperti Google Go muncul.

Pilih kuncinya

Seiring waktu, banyak pilihan telah muncul yang memperbaiki - tetapi tidak menghilangkan - batasan GIL. Salah satu taktik standar adalah meluncurkan beberapa contoh CPython dan berbagi konteks dan status di antara mereka; setiap contoh berjalan secara independen satu sama lain dalam proses terpisah. Namun seperti yang dijelaskan Jeff Knupp, keuntungan yang diperoleh dengan menjalankan secara paralel dapat hilang dengan upaya yang diperlukan untuk berbagi status, jadi teknik ini paling sesuai untuk operasi jangka panjang yang mengumpulkan hasil dari waktu ke waktu.

Ekstensi C tidak terikat oleh GIL, begitu banyak pustaka untuk Python yang membutuhkan kecepatan (seperti pustaka matematika dan statistik Numpy) dapat berjalan di banyak inti. Namun batasan di CPython sendiri tetap ada. Jika cara terbaik untuk menghindari GIL adalah dengan menggunakan C, itu akan membuat lebih banyak programmer menjauh dari Python dan menuju C.

PyPy, versi Python yang mengkompilasi kode melalui JIT, tidak menyingkirkan GIL tetapi membuatnya hanya dengan menjalankan kode lebih cepat. Dalam beberapa hal, ini bukanlah pengganti yang buruk: Jika kecepatan adalah alasan utama Anda mengincar multithreading, PyPy mungkin dapat memberikan kecepatan tanpa komplikasi multithreading.

Akhirnya, GIL itu sendiri dikerjakan ulang dengan Python 3, dengan handler peralihan thread yang lebih baik. Tetapi semua asumsi yang mendasarinya - dan batasan - tetap ada. Masih ada GIL, dan masih menahan proses.

Tidak ada GIL? Tidak masalah

Terlepas dari semua ini, pencarian Python tanpa GIL, kompatibel dengan aplikasi yang ada, terus berlanjut. Implementasi lain dari Python telah menghilangkan GIL sepenuhnya, tetapi dengan biaya. Jython, misalnya, berjalan di atas JVM dan menggunakan sistem pelacakan objek JVM, bukan GIL. IronPython mengambil pendekatan yang sama melalui CLR Microsoft. Namun keduanya mengalami kinerja yang tidak konsisten, dan terkadang berjalan jauh lebih lambat daripada CPython. Mereka juga tidak dapat langsung berinteraksi dengan kode C eksternal, sehingga banyak aplikasi Python yang ada tidak akan berfungsi.

PyParallel, proyek yang dibuat oleh Trent Nelson dari Continuum Analytics, adalah "percabangan eksperimental dan bukti konsep Python 3 yang dirancang untuk secara optimal mengeksploitasi beberapa inti CPU". Ini tidak menghapus GIL, tetapi memperbaiki dampaknya dengan mengganti asyncmodul, sehingga aplikasi yang digunakan  asyncuntuk paralelisme (seperti I / O multithread seperti server web) mendapatkan keuntungan paling besar. Proyek ini tidak aktif selama beberapa bulan, tetapi dokumentasinya menyatakan bahwa pengembangnya merasa nyaman meluangkan waktu untuk memperbaikinya, sehingga pada akhirnya dapat dimasukkan ke dalam CPython: "Tidak ada yang salah dengan lambat dan mantap selama Anda menuju ke arah yang benar. "

Salah satu proyek yang sudah berjalan lama oleh pencipta PyPy adalah versi Python yang menggunakan teknik yang disebut "memori transaksional perangkat lunak" (PyPy-STM). Keuntungannya, menurut pencipta PyPy, adalah "Anda dapat melakukan perubahan kecil pada program Anda yang sudah ada, program yang tidak multithread dan membuatnya menggunakan banyak inti."

PyPy-STM terdengar seperti sihir, tetapi memiliki dua kekurangan. Pertama, ini adalah pekerjaan yang sedang berjalan yang saat ini hanya mendukung Python 2.x, dan kedua, masih membutuhkan kinerja yang baik untuk aplikasi yang berjalan pada satu inti. Karena salah satu ketentuan yang dikutip oleh pencipta Python Guido van Rossum untuk setiap upaya untuk menghapus GIL dari CPython adalah bahwa penggantinya tidak boleh menurunkan kinerja untuk aplikasi single-core, single-threaded, perbaikan seperti ini tidak akan mendarat di CPython dalam keadaannya saat ini.

Cepat tunggu

Larry Hastings, pengembang inti Python, membagikan beberapa pandangannya di PyCon 2016 tentang bagaimana GIL dapat dihapus. Hastings mendokumentasikan upayanya untuk menghapus GIL dan dengan demikian berakhir dengan versi Python yang tidak memiliki GIL, tetapi berjalan sangat lambat karena cache yang hilang terus-menerus.

Anda bisa kehilangan GIL, kesimpulan Hastings, tetapi Anda perlu memiliki beberapa cara untuk menjamin bahwa hanya satu utas pada satu waktu yang memodifikasi objek global - misalnya, dengan memiliki utas khusus dalam penerjemah yang menangani perubahan status tersebut.

Salah satu kabar baik jangka panjang adalah jika dan ketika CPython melepaskan GIL, pengembang yang menggunakan bahasa tersebut sudah siap untuk mengeksploitasi multithreading. Banyak perubahan sekarang dimasukkan ke dalam sintaks Python, seperti antrian dan async/ awaitkata kunci untuk Python 3.5, memudahkan pembagian tugas di seluruh inti pada level tinggi.

Namun, jumlah pekerjaan yang diperlukan untuk membuat Python GIL-less semuanya tetapi menjamin itu akan muncul pertama kali dalam implementasi terpisah seperti PyPy-STM. Mereka yang ingin mencoba sistem tanpa GIL dapat melakukannya melalui upaya pihak ketiga tersebut, tetapi CPython asli kemungkinan besar masih belum tersentuh untuk saat ini. Semoga penantiannya tidak lebih lama lagi.