Dokumentasi Python 3.7
Saya juga ingin menyoroti kutipan berikut dari dokumentasi Pythonthreading
:
Detail implementasi CPython: Di CPython, karena Global Interpreter Lock, hanya satu utas yang dapat mengeksekusi kode Python sekaligus (meskipun pustaka yang berorientasi kinerja tertentu mungkin mengatasi batasan ini). Jika Anda ingin aplikasi Anda memanfaatkan sumber daya komputasi mesin multi-core dengan lebih baik, Anda disarankan untuk menggunakan multiprocessing
atau concurrent.futures.ProcessPoolExecutor
. Namun, threading masih merupakan model yang tepat jika Anda ingin menjalankan beberapa tugas yang terikat I / O secara bersamaan.
Tautan ini ke entri Glosariumglobal interpreter lock
yang menjelaskan bahwa GIL menyiratkan bahwa paralelisme berulir dalam Python tidak cocok untuk tugas yang terikat CPU :
Mekanisme yang digunakan oleh juru bahasa CPython untuk memastikan bahwa hanya satu utas yang mengeksekusi bytecode Python sekaligus. Ini menyederhanakan implementasi CPython dengan membuat model objek (termasuk tipe bawaan yang kritis seperti dict) secara implisit aman terhadap akses bersamaan. Mengunci seluruh juru bahasa membuatnya lebih mudah bagi juru bahasa untuk menjadi multi-threaded, dengan mengorbankan banyak paralelisme yang diberikan oleh mesin multi-prosesor.
Namun, beberapa modul ekstensi, baik standar atau pihak ketiga, dirancang untuk melepaskan GIL saat melakukan tugas-tugas yang intensif secara komputasi seperti kompresi atau hashing. Juga, GIL selalu dirilis saat melakukan I / O.
Upaya masa lalu untuk menciptakan juru bahasa "bebas-ulir" (yang mengunci data bersama pada granularitas yang jauh lebih halus) belum berhasil karena kinerja menderita dalam kasus prosesor tunggal yang umum. Diyakini bahwa mengatasi masalah kinerja ini akan membuat implementasi jauh lebih rumit dan oleh karena itu lebih mahal untuk dipertahankan.
Kutipan ini juga menyiratkan bahwa dikt dan karenanya penugasan variabel juga aman sebagai detail implementasi CPython:
Selanjutnya, dokumen untuk multiprocessing
paket menjelaskan bagaimana mengatasi GIL dengan proses pemijahan sambil mengekspos antarmuka yang mirip dengan threading
:
multiprocessing adalah paket yang mendukung proses pemijahan menggunakan API yang mirip dengan modul threading. Paket multi-pemrosesan menawarkan konkurensi lokal dan jarak jauh, secara efektif menuntun Global Interpreter Lock dengan menggunakan subproses alih-alih utas. Karena ini, modul multiprosesing memungkinkan programmer untuk memanfaatkan sepenuhnya beberapa prosesor pada mesin yang diberikan. Ini berjalan di kedua Unix dan Windows.
Dan dokumen untukconcurrent.futures.ProcessPoolExecutor
menjelaskan itu digunakan multiprocessing
sebagai backend:
Kelas ProcessPoolExecutor adalah subkelas Pelaksana yang menggunakan kumpulan proses untuk mengeksekusi panggilan secara tidak sinkron. ProcessPoolExecutor menggunakan modul multiprocessing, yang memungkinkannya untuk melakukan side-step Lock Global Interpreter tetapi juga berarti bahwa hanya objek yang dapat di-pickable yang dapat dieksekusi dan dikembalikan.
yang harus dikontraskan dengan kelas dasar lainnya ThreadPoolExecutor
yang menggunakan utas bukannya proses
ThreadPoolExecutor adalah subkelas Pelaksana yang menggunakan kumpulan utas untuk melakukan panggilan secara tidak sinkron.
dari mana kami menyimpulkan bahwa ThreadPoolExecutor
hanya cocok untuk tugas terikat I / O, sementara ProcessPoolExecutor
juga dapat menangani tugas terikat CPU.
Pertanyaan berikut menanyakan mengapa GIL ada di tempat pertama: Mengapa Global Interpreter Lock?
Percobaan proses vs utas
Di Multiprocessing vs Threading Python saya telah melakukan analisis eksperimental proses vs threads di Python.
Pratinjau cepat hasil: