PEP 703 disetujui untuk menjadikan GIL di CPython sebagai opsi
(discuss.python.org)- Python Steering Council berniat menerima PEP 703 untuk menjadikan GIL sebagai opsi di CPython, dan respons komunitas terhadap proposal no-GIL maupun PEP 703 secara umum juga positif
- Tujuan jangka panjangnya adalah menyatukan ke build no-GIL tunggal, dan menghindari situasi di mana build with-GIL dan no-GIL serta ekosistem extension module terpecah secara permanen
- Dalam proses transisi, kompatibilitas mundur adalah batasan utama, dan kode pihak ketiga yang diubah untuk mendukung no-GIL juga harus tetap berjalan di build with-GIL
- Rencananya adalah transisi 3 tahap: build eksperimental jangka pendek, build yang didukung di jangka menengah, dan build default di jangka panjang; build eksperimental bisa masuk ke Python 3.13, tetapi jika mundur ke 3.14 juga tidak dianggap masalah
- Sebelum beralih ke build default, perlu dipastikan dukungan komunitas serta pengalaman API, packaging, dan distribusi; jika kebingungannya lebih besar daripada manfaatnya, maka PEP 703 harus dihentikan dan dicari solusi lain
Arah penerimaan PEP 703 oleh Steering Council
- Python Steering Council menyatakan niat untuk menerima PEP 703
- Dalam survei proposal no-GIL, respons yang muncul secara umum positif, dan Steering Council juga pada dasarnya berpandangan positif terhadap ide umum maupun PEP 703 itu sendiri
- Namun, detail penerimaannya masih sedang dikerjakan dan akan difinalkan dalam beberapa minggu ke depan
Prinsip transisi tanpa percabangan permanen
- Dalam jangka panjang, kemungkinan dalam periode lebih dari 5 tahun, build no-GIL harus menjadi satu-satunya build
- Mereka tidak menginginkan situasi di mana build with-GIL dan no-GIL terpisah secara permanen
- Mereka juga ingin menghindari struktur di mana ekosistem extension module terbelah permanen menjadi dua build
- Kompatibilitas mundur harus ditangani dengan sangat hati-hati
- Mereka tidak ingin menciptakan situasi transisi Python 3 lagi
- Walaupun kode pihak ketiga diubah untuk mendukung build no-GIL, perubahan itu tetap harus berjalan di build with-GIL
- Masalah kompatibilitas mundur dengan versi Python sebelumnya perlu ditangani secara terpisah
- Ini bukan Python 4
- Persyaratan kompatibilitas ABI, detail kedua build, dan dampaknya terhadap kompatibilitas mundur masih dalam peninjauan
Hal yang harus dipastikan sebelum mengubah default
- Sebelum build no-GIL dijadikan default, perlu dipastikan bahwa dukungan komunitas sudah memadai
- Tidak bisa hanya mengubah default lalu membiarkan komunitas mencari sendiri pekerjaan yang diperlukan
- Core developer perlu merasakan langsung mode build baru dan unsur-unsur di sekitarnya
- Saat merapikan thread safety pada kode yang ada, mungkin akan dibutuhkan C API dan Python API yang baru
- Wawasan yang didapat dari proses itu harus dibagikan ke komunitas Python
- Perlu dipastikan bahwa perubahan yang diinginkan core developer dan perubahan yang diminta dari komunitas berada pada tingkat yang dapat diterima
- Hingga no-GIL dijadikan default, harus tetap dimungkinkan untuk mengubah arah jika perubahan yang terjadi dianggap menimbulkan kebingungan terlalu besar dan manfaatnya terlalu kecil
- Dalam kasus ini, keputusan untuk membatalkan seluruh pekerjaan juga harus dimungkinkan
- Karena itu, kode yang khusus untuk no-GIL perlu cukup dapat diidentifikasi
Rencana transisi 3 tahap
- Dalam jangka pendek, build no-GIL akan ditambahkan sebagai mode build eksperimental
- Kemungkinan bisa masuk ke Python 3.13
- Jika mundur ke Python 3.14 juga tidak dianggap sebagai masalah
- Status eksperimental dimaksudkan untuk memperjelas bahwa core developer mendukung mode build tersebut, tetapi komunitas tidak bisa diharapkan langsung mendukungnya
- Dibutuhkan waktu agar dukungan komunitas memungkinkan dari sisi desain API, packaging, dan distribusi
- Distribusi tidak dianjurkan menjadikan build no-GIL eksperimental sebagai interpreter default
- Dalam jangka menengah, build no-GIL akan menjadi target yang didukung, tetapi belum dijadikan default
- Diperlukan keyakinan bahwa dukungan komunitas sudah cukup untuk memungkinkan penggunaan produksi
- Pada tahap ini, akan ditentukan tanggal target atau versi Python untuk menjadikan no-GIL sebagai default
- Waktunya sangat bergantung pada kompatibilitas mundur perubahan API, penanganan stable ABI, dan banyaknya pekerjaan yang menurut komunitas perlu dilakukan
- Ini bisa memakan waktu setidaknya 1~2 tahun, atau lebih lama
- Setelah dinyatakan didukung, sebagian distributor mungkin mulai menyediakan no-GIL sebagai default, tetapi hal itu juga bisa bergantung pada seberapa banyak paket Python yang saat itu sudah mendukung no-GIL
- Dalam jangka panjang, no-GIL akan dijadikan default dan sisa-sisa GIL akan dihapus
- Kompatibilitas mundur tidak akan dirusak tanpa alasan
- Jika dua mode build umum dipertahankan terlalu lama, beban komunitas bisa membesar, misalnya karena sumber daya pengujian dan skenario debugging menjadi dua kali lipat
- Namun hal ini juga tidak bisa diburu-buru, dan tahap ini bisa memakan waktu hingga 5 tahun
Evaluasi berkelanjutan dan kemungkinan penghentian
- Sepanjang proses, bukan hanya Steering Council tetapi juga core developer harus terus mengevaluasi ulang progres dan jadwal yang diusulkan
- Mereka tidak ingin pekerjaan ini berubah menjadi pertarungan kompatibilitas mundur selama 10 tahun lagi
- Jika muncul tanda bahwa PEP 703 akan menjadi masalah, prosesnya harus bisa dihentikan dan solusi lain dicari
- Perlu ada pemeriksaan berkala untuk memastikan apakah pekerjaan yang berlanjut ini memang sepadan nilainya
1 komentar
Pendapat di Hacker News
Selama puluhan tahun, banyak kode pustaka C memiliki peringatan di manual bahwa kode tersebut tidak stabil dalam konteks asinkron, reentrant, dan rekursif
Meski begitu, kita belajar cara menghadapinya, dan versi-versi yang aman untuk reentrancy dirilis secara bertahap tanpa membuat API terlalu tidak stabil
Ada hal-hal seperti parsing string yang melakukan tokenisasi di tempat, pemanggilan DNS yang memakai buffer statis, dan kode yang bergantung pada perilaku stack khas Vax; menurut saya GIL adalah berkah sekaligus kutukan
Berkat itu, sepertinya saya jadi terbiasa memeriksa dokumentasi bahkan untuk API yang cukup saya kenal, karena mungkin saja ada detail penting yang terlewat atau berubah
Saat itu, ketika mengerjakan C++ lintas platform, Java yang pertama kali saya lihat sudah memiliki konkurensi, garbage collection, dan berbagai fitur yang lebih mudah dipakai daripada C++ sejak awal, dan saya yakin Java akan sangat besar
Setelah itu para developer arus utama mulai memakai Python; sejauh yang saya ingat, Python awalnya sederhana sebagai bahasa ekstensi yang bisa di-embed, jadi GIL juga lebih masuk akal
Ini bukan seseorang menyalakan sebuah sakelar lalu memecahkan banyak sekali kode C yang meragukan sekaligus
Sekarang sudah ada CPU 128-core, dan di era ketika CPU murah pun punya 6 core, batasan yang terikat pada performa satu core akan makin besar seiring waktu
Awalnya saya percaya itu masalah yang akan selesai dalam beberapa minggu, paling lama beberapa bulan; ternyata saya terlalu tidak tahu
Di C, interaksi dengan fungsi yang tidak thread-safe jauh lebih langsung, dan ketika memakai C biasanya orang lebih berhati-hati
Di Python ada modul-modul C utuh yang memiliki state global; setelah memuat sekitar 10 modul dan menambahkan kompleksitas interpreter, tak lama kemudian tidak ada yang tahu apa yang sedang terjadi
Bahkan sekarang sebagian besar developer, bahkan core developer sekalipun, tidak memeriksa kebocoran memori; saya tidak merasa mereka akan menjalankan tsan, dan kalaupun dijalankan kemungkinan hanya pada rangkaian tes kecil yang mencakup 10% kode
Melihat praktik pengembangan perangkat lunak di Python, terutama di sisi AI, saya sangat pesimistis terhadap fitur ini
Ini memang menarik
Python sebagian besar tersusun dari pustaka bersama C yang ditulis dengan pengetahuan bahwa mereka boleh bergantung pada lock global
Sebagian cukup sederhana sehingga bisa berjalan baik tanpa lock, tetapi yang lain tetap membutuhkan lock dan sekarang akan mendapat tekanan untuk berjalan tanpa GIL
Sebagian dari mereka akan mengimplementasikan lock sendiri di dalam lingkupnya, dan mungkin yang benar-benar kurang dari Python selama ini adalah pemanggilan mutex ad hoc yang tersebar di seluruh ekosistem
Saya tidak pernah menyangka Python akan rusak dengan cara memasukkan data race dan deadlock atas nama performa
Membuat pustaka C yang ditulis dengan asumsi adanya lock global menjadi thread-safe adalah pekerjaan yang bahkan pakar konkurensi pun sarankan untuk dihindari, dan jenis pekerjaan yang mudah salah saat diimplementasikan
Hipotesis saya, kebanyakan orang yang menulis ekstensi C Python bukanlah pakar konkurensi, melainkan programmer bagus yang tidak menghindari tantangan; dengan kombinasi ini, data race/hang/segfault tampak hampir tak terelakkan
Namun ekspektasi untuk mengubahnya menjadi opt-in lima tahun lagi terlalu optimistis
Semua developer pustaka harus memperbaiki pustaka mereka sendiri, bahkan pustaka Python, dan itu pekerjaan berat; kalaupun dikerjakan dengan baik, hampir tidak ada yang menyadarinya sehingga sulit mendapat imbalan
Banyak pustaka sama sekali tidak punya use case multiprocessing, dan pustaka besar pasti akan memunculkan bug halus, sehingga keluhan yang tak bisa direproduksi dan developer yang menyerah tampak seperti hasil yang terjamin
Python yang memiliki GIL pun mendukung thread, jadi pustaka seperti ini setidaknya semestinya aman untuk reentrancy
Jika sebuah pustaka reentrant tetapi tidak thread-safe, menambahkan satu lock global yang membungkus semua pemanggilan bisa saja cukup, dan ini cukup mirip dengan apa yang dilakukan GIL
Membuat pustaka yang ada berjalan tanpa GIL dalam banyak kasus tampaknya relatif lurus ke depan, meskipun paralelisme bisa dikorbankan
Masalah utamanya sepertinya adalah pustaka yang melakukan callback dari sisi C ke runtime Python
Pertanyaan yang naif, tapi dengan adanya paket asyncio dan multiprocessing, rasanya siapa yang membutuhkan No-GIL?
Saya belum pernah mengalami masalah karena GIL di Python, dan selalu bisa mengakalinya dengan menjalankan ThreadPool atau ProcessPool, atau memakai pustaka asinkron bila perlu
Saya penasaran apakah ada kasus penggunaan No-GIL yang tidak bisa diselesaikan dengan multiprocessing
Saya tadinya berpikir eksekusi single-thread tanpa overhead alat primitif konkurensi adalah yang terbaik untuk komputasi berkinerja tinggi. Seperti yang ditunjukkan LMAX Disruptor
asyncio pada dasarnya single-thread sehingga hanya satu core, sementara multiprocessing memakai banyak core sehingga lebih baik untuk performa, tetapi tiap proses relatif berat dan menambah overhead memori bersama
Multithreading berbasis GIL hanya satu core dan juga sulit ditulis dengan benar
Multithreading No-GIL memakai banyak core tetapi sulit digunakan, dan saya tidak tahu implementasinya, tetapi memori bersama seharusnya lebih cepat daripada multiprocessing
Jika merancang sistem baru, saya setuju untuk hampir semua kasus penggunaan Python sebaiknya jangan menyentuh thread dan gunakan asyncio/multiprocessing
Program Python yang membutuhkan multithreading cepat sering kali memang seharusnya tidak ditulis dengan Python sejak awal, tetapi karena sudah ada orang yang menulis kode intensif CPU dengan Python, No-GIL jadi praktis
Misalnya ada server web yang memakai state bersama untuk merespons banyak klien secara bersamaan, dan multiprocessing memakai pickle untuk mengirim dan menerima data sehingga overhead performanya besar
Contohnya, jika ingin menaruh struktur data 1GB di memori dan melakukan komputasi paralel, multiprocessing sulit menanganinya dengan performa baik
Dengan pickle, tidak semua objek bisa dibagikan, dan error objek yang tidak bisa di-pickle sangat sulit di-debug pada struktur data yang kompleks
Terutama objek yang dibuat pustaka native bisa saja tidak dapat dibagikan
Pemrosesan yang harus berbagi state saat berjalan juga sangat sulit dengan modul multiprocessing, bahkan Prometheus exporter untuk Flask pun membutuhkan hack aneh memakai direktori sementara untuk mengumpulkan statistik dari semua proses
Di banyak aplikasi DeepMind, mereka ingin menjalankan sekitar 50–100 thread per proses, tetapi katanya GIL sering menjadi bottleneck bahkan di bawah 10 thread
Sebagai jalan pintas mereka kadang memakai subprocess, tetapi dalam banyak kasus overhead komunikasi antarproses menjadi terlalu besar, sehingga pada akhirnya sebagian besar codebase Python dipindahkan ke C++
Untuk penggunaan rata-rata seperti aplikasi web, multiprocessing mungkin cukup, tetapi pada workload AI skala besar seperti di Google dan DeepMind, GIL benar-benar membatasi penggunaan Python
Ini juga alasan Meta ingin mengalokasikan tiga tahun kerja engineer untuk upaya ini: https://news.ycombinator.com/item?id=36643670
Sesuai namanya, ia hanya benar-benar membantu pada masalah I/O-bound
Berbagi data antar banyak proses itu sangat menyakitkan, dan menggabungkan kontrol data dengan orkestrasi proses lebih menyakitkan lagi
Proses itu mahal, dan karena kesulitan berbagi data seperti disebutkan tadi, greenlet juga sulit menjadi alternatif nyata
Namun di bidang seperti AI dan data science, tempat Python punya porsi besar, kemampuan menjalankan banyak thread CPU/GPU-bound adalah keuntungan besar
Banyak ekstensi C tidak ditulis dengan mempertimbangkan multithreading, jadi ini bisa menimbulkan masalah, dan rasanya memang akan begitu
Contoh kecil yang tidak aman jika
lstbisa diakses dari thread lain ada di sini: https://news.ycombinator.com/item?id=36649769Bahkan sekarang pun, jika kode C memanggil balik ke bytecode Python lewat metode
__del__dan bytecode itu cukup panjang, mungkin sekitar 100 instruksi, context switch bisa terjadiNamun itu kasus yang sangat jarang, dan banyak kode ekstensi C tidak ditulis dengan mempertimbangkan situasi seperti ini
Pengguna ekstensi C mungkin saja mengandalkan fakta bahwa ekstensi itu dieksekusi secara atomik
Misalnya pola memasukkan dan mengambil array numpy lewat thread pool saat ini berjalan baik, tetapi bisa rusak tanpa GIL
Karena itu proposal dan arah pengerjaannya adalah menjadikan mode non-GIL sepenuhnya opsional dan tidak menjadi default
Segelintir orang berani yang mengaktifkannya harus siap menghabiskan banyak sekali waktu untuk menemukan dan memperbaiki race condition halus di kode pustaka Python yang sudah berumur puluhan tahun
Para pengadopsi awal akan banyak menderita, atau yang lebih mungkin, membatasi penggunaan non-GIL hanya pada proses khusus yang sangat terspesialisasi dengan dependensi seminimal mungkin
Kita bergerak dari kondisi sekadar menduga ada masalah ke kondisi tahu persis di mana masalahnya, dan sisanya tinggal mengikis daftar itu satu per satu
Bisa dengan menambahkan semacam mutex di sekitar kode, atau menggantinya dengan implementasi alternatif non-native yang lebih kecil kemungkinan menimbulkan masalah
Argumen penentangnya terutama bahwa pekerjaannya banyak, bukan bahwa itu mustahil
Jika ada cukup orang yang mengerjakannya, hasilnya bisa muncul
Kalau tidak, mereka akan mengumumkan rencana untuk tiba-tiba menghapus GIL sepenuhnya, alih-alih pendekatan bertahap yang membiarkan orang memilih sendiri mode No-GIL
Cukup ingat transisi dari teks ke Unicode, dari 32-bit ke 64-bit, dari Intel ke ARM, dan Y2K
No-GIL adalah perubahan yang jauh lebih kecil, dan bisa mengikuti jalur transisi yang sama tanpa memutus kompatibilitas secara radikal
Kalaupun ada yang rusak, akan ada cara yang terdefinisi dengan baik untuk menangani kasus seperti itu
Bagaimanapun, kita berhasil melewati semua transisi itu, dan senang melihat kita bergerak maju
Ini akan membuka lebih banyak area yang selama ini ditandai sebagai mustahil
Salah satu hal yang dilakukan Swift awal dengan baik adalah memasukkan breaking changes ke dalam janji rilis, sehingga semua orang tahu posisinya dan bisa beradaptasi dengan baik
Kadang saya berharap Python juga menempuh jalan yang sama
Dari 32-bit ke 64-bit, ke ARM, maupun Y2K, semuanya bisa diuji apakah bekerja atau tidak
Tentu saja pengujian bisa saja tidak mencakup kasus kegagalan, tetapi pengujian yang dilakukan bersifat deterministik
Namun di sini, sebanyak apa pun pengujian dilakukan, jawabannya adalah “benar, atau belum menyentuh race condition yang tepat”
Memang secara eksplisit dikatakan bahwa mereka tidak ingin mengulang skenario transisi Python 3, tetapi pendekatan saat ini terasa menakutkan karena sangat dekat dengan jalur itu
Banyak hal bergantung pada komunitas Python dan kanal distribusinya
Komunitas bisa gagal mengadopsinya tepat waktu, atau distribusi seperti Ubuntu, Fedora, dan Anaconda bisa terburu-buru maju lebih dulu
Masih terlalu dini untuk memastikan, tetapi saya mempertanyakan seberapa besar kendali nyata yang dimiliki Steering Council untuk menghindari skenario seperti ini
5 tahun terlalu lama bagi Python untuk memiliki dua mode
Setengah dekade sudah cukup untuk membuat kedua mode mengeras menjadi status quo, dan setelah itu pun artikel Stack Overflow lama akan tetap ada
Saya tidak optimistis bahwa 5 tahun tidak akan berubah menjadi 10 tahun ketidakpastian dan kerusakan
Sebaliknya, 5 tahun juga mungkin terlalu singkat untuk membongkar semua kode C, memperbaikinya, mengujinya, dan menyebutnya matang
Perusahaan-perusahaan yang menjanjikan dukungan mungkin akan mengonversi beberapa proyek secara mekanis, lalu mengganggu developer sebenarnya atau mengancam dengan fork
Bug-bugnya akan dipoles selama bertahun-tahun oleh developer sungguhan yang tidak dibayar
Namun Python membutuhkan semacam “keberhasilan”, dan ini menjadi kalimat promosi yang bagus
Di dunia Python, akurasi tampaknya tidak terlalu penting
Karena sejarah itu, terdengar seolah mereka lebih memilih mempertahankan dua mode eksekusi di dalam CPython 3 daripada bergerak menuju transisi mayor lain
Untungnya mereka sangat sadar bahwa ini bisa dengan mudah menjadi bencana Python 4
Harus sangat berhati-hati agar tidak secara tidak sengaja memengaruhi perilaku yes-GIL
Jika suatu bentuk GIL yang diemulasikan tidak persis sama dengan GIL nyata, segala macam kasus aneh bisa terjadi
Pertama, mereka tidak ingin itu terjadi
Kedua, jika itu terjadi, mereka akan cepat menyerah
Keduanya penting, tetapi tampaknya masih kurang bagian ketiga yang krusial: “dan beginilah cara kami mencapainya”
Mereka sudah mengatakan GIL dan No-GIL bisa hidup berdampingan selama 5 tahun atau lebih
Bagi pembuat tool, itu berarti biaya menjadi dua kali lipat setidaknya selama 5 tahun ke depan
Karena, baik untuk penggunaan produktif maupun eksperimental, orang akan ingin memakai tool di kedua mode
GIL adalah Global Interpreter Lock
Penjelasan yang bagus ada di sini: https://realpython.com/python-gil/
Ada dua masalah besar di sini
Pertama, sebagian perbaikan memang layak memutus kompatibilitas mundur, dan penghapusan GIL adalah perbaikan seperti itu
Apakah perubahan di Python 3 memang layak untuk itu masih bisa diperdebatkan, dan
printmenjadi fungsi tampaknya tidak terlalu bernilai secara khususNamun transisi 2-ke-3 agak dibesar-besarkan oleh minoritas yang bersuara keras, dan dari pengalaman saya memindahkan lebih dari 5 codebase dari 2 ke 3, sebagian besar tidak banyak masalah
Masalah terbesar adalah codebase yang sudah menjadi tumpukan library terbengkalai karena developer sebelumnya menarik library untuk segala hal, dan kode seperti ini akan tetap bermasalah meskipun bahasa intinya tidak memutus kompatibilitas
Jawabannya bukan mendorong agar bahasa tidak pernah boleh memutus kompatibilitas selamanya, melainkan tidak berharap bahwa mengambil seluruh pip akan menjadi strategi yang berkelanjutan
Saat ini Steering Council sudah terlalu banyak disalahkan oleh minoritas yang bersuara keras sehingga takut pada perubahan yang merusak kompatibilitas
Namun penghapusan GIL adalah bagian yang terlalu fundamental dari cara kerja Python sehingga seharusnya memang menjadi breaking change; lebih baik mengakuinya dan menyusun rencana transisi, daripada takut kepada pengguna lalu mencoba hal mustahil untuk membuatnya tidak merusak kompatibilitas tanpa mengakui kenyataan
Di Python 3.11 pun codebase saya rusak, dan perbaikannya tidak sulit, tetapi saya berharap komunikasi bahwa hal seperti ini bisa terjadi dilakukan dengan lebih baik
Kedua, masalah yang lebih mendasar adalah banyak fitur Python lain dibuat dengan berpusat pada GIL
Khususnya paradigma asinkron sangat bermakna karena GIL; jika tidak ada GIL, jika dilihat kembali, model aktor send/recv ala Erlang akan menjadi arah yang jauh lebih baik
Sulit untuk membalikkan hal ini, dan rasanya Python terdorong menjadi kumpulan fitur yang kurang kohesif dan tidak terlalu cocok satu sama lain, sehingga terlihat seperti terlalu sedikit dan terlalu terlambat
Terima kasih kepada para pengembang inti Python dan Steering Council; Python adalah salah satu bahasa favorit saya, bersama Java dan C
Saya sangat menyambut multithreading sungguhan di Python
Tergantung proyeknya, saya menggunakan multiprocessing maupun multithreading; contoh multiprocessing ada di [0], dan contoh penggunaan Python Threads untuk pekerjaan yang banyak I/O ada di [1]
Namun, menggunakan thread sungguhan akan jauh lebih efisien
Thread dapat saling mengirim data dalam jumlah sembarang sebagai satu operasi atomik yang nyaris seketika, tetapi hal itu tidak mungkin dengan antarmuka loopback lokal, multiprocessing, atau pipe
Saya sedang mengerjakan arsitektur multithreading yang saya sebut “three tier multithreading architecture”
https://github.com/samsquire/three-tier-multithreaded-archit...
Tujuannya adalah server yang sangat skalabel dan berkinerja tinggi, tetapi Python mungkin bukan alat yang tepat untuk pekerjaan itu
[0]: https://news.ycombinator.com/item?id=36897054 penjelasan penggunaan multiprocessing
[1]: https://devops-pipeline.com/ contoh penggunaan multithreading