Saya sedikit bingung apakah multithreading berfungsi dengan Python atau tidak.
Saya tahu ada banyak pertanyaan tentang ini dan saya telah membaca banyak di antaranya, tetapi saya masih bingung. Saya tahu dari pengalaman saya sendiri dan telah melihat orang lain memposting jawaban dan contoh mereka sendiri di sini di StackOverflow bahwa multithreading memang dimungkinkan dengan Python. Jadi mengapa semua orang terus mengatakan bahwa Python dikunci oleh GIL dan hanya satu utas yang dapat berjalan dalam satu waktu? Ini jelas berhasil. Atau apakah ada perbedaan yang tidak saya dapatkan di sini?
Banyak poster / responden juga tetap menyebutkan bahwa threading dibatasi karena tidak menggunakan banyak core. Tapi saya akan mengatakan mereka masih berguna karena mereka melakukan pekerjaan secara bersamaan dan dengan demikian menyelesaikan beban kerja gabungan lebih cepat. Maksud saya, mengapa bahkan ada modul utas Python?
Memperbarui:
Terima kasih atas semua jawaban sejauh ini. Cara saya memahaminya adalah bahwa multithreading hanya akan berjalan secara paralel untuk beberapa tugas IO, tetapi hanya dapat berjalan satu per satu untuk beberapa tugas inti yang terikat CPU.
Saya tidak sepenuhnya yakin apa artinya ini bagi saya dalam istilah praktis, jadi saya hanya akan memberikan contoh jenis tugas yang ingin saya multithread. Misalnya, saya ingin mengulang melalui daftar string yang sangat panjang dan saya ingin melakukan beberapa operasi string dasar pada setiap item daftar. Jika saya memisahkan daftar, mengirim setiap sublist untuk diproses oleh kode loop / string saya di thread baru, dan mengirim hasilnya kembali ke antrean, apakah beban kerja ini akan berjalan kira-kira pada waktu yang sama? Yang paling penting apakah ini secara teoritis akan mempercepat waktu yang diperlukan untuk menjalankan skrip?
Contoh lain mungkin jika saya dapat membuat dan menyimpan empat gambar berbeda menggunakan PIL di empat utas berbeda, dan apakah ini lebih cepat daripada memproses gambar satu per satu demi satu? Saya kira komponen kecepatan inilah yang benar-benar saya pertanyakan daripada terminologi yang benar.
Saya juga tahu tentang modul multiprosesing tetapi minat utama saya saat ini adalah untuk beban tugas kecil-menengah (10-30 detik) dan jadi menurut saya multithreading akan lebih sesuai karena subproses bisa lambat untuk dimulai.
sumber
Jawaban:
GIL tidak mencegah penguliran. Semua yang dilakukan GIL adalah memastikan hanya satu utas yang menjalankan kode Python pada satu waktu; kontrol masih beralih di antara utas.
Apa yang GIL cegah kemudian, adalah menggunakan lebih dari satu inti CPU atau CPU terpisah untuk menjalankan utas secara paralel.
Ini hanya berlaku untuk kode Python. Ekstensi C dapat dan memang merilis GIL untuk memungkinkan beberapa utas kode C dan satu utas Python dijalankan di beberapa inti. Ini meluas ke I / O yang dikendalikan oleh kernel, seperti
select()
panggilan untuk membaca dan menulis soket, membuat Python menangani peristiwa jaringan secara cukup efisien dalam pengaturan multi-inti multi-utas.Apa yang kemudian dilakukan oleh banyak penerapan server, adalah menjalankan lebih dari satu proses Python, agar OS menangani penjadwalan antar proses untuk memanfaatkan inti CPU Anda secara maksimal. Anda juga dapat menggunakan
multiprocessing
pustaka untuk menangani pemrosesan paralel di beberapa proses dari satu basis kode dan proses induk, jika itu sesuai dengan kasus penggunaan Anda.Perhatikan bahwa GIL hanya berlaku untuk implementasi CPython; Jython dan IronPython menggunakan implementasi threading yang berbeda (masing-masing VM Java asli dan thread runtime umum .NET).
Untuk mengatasi pembaruan Anda secara langsung: Setiap tugas yang mencoba untuk mendapatkan peningkatan kecepatan dari eksekusi paralel, menggunakan kode Python murni, tidak akan melihat percepatan karena kode Python berulir dikunci ke satu utas yang dieksekusi pada satu waktu. Jika Anda mencampur ekstensi C dan I / O, bagaimanapun (seperti operasi PIL atau numpy) dan kode C apa pun dapat berjalan secara paralel dengan satu utas Python aktif.
Python threading sangat bagus untuk membuat GUI yang responsif, atau untuk menangani beberapa permintaan web singkat di mana I / O lebih menjadi penghambat daripada kode Python. Ini tidak cocok untuk memparalelkan kode Python intensif komputasi, tetap berpegang pada
multiprocessing
modul untuk tugas-tugas semacam itu atau mendelegasikan ke perpustakaan eksternal khusus.sumber
urllib.urlopen()
?), Untuk memanggil satu skrip Python dari dalam Python GUI, dan memanggil beberapa operasi PIL (misalnyaImage.transform()
) dan numpy (misalnyanumpy.array()
) dengan utas. Dan Anda memberikan beberapa contoh lagi dalam komentar Anda seperti menggunakan beberapa utas untuk membaca file (mis.f.read()
?). Saya tahu daftar lengkap tidak mungkin, hanya ingin jenis contoh yang Anda berikan dalam pembaruan Anda. Bagaimanapun, terima jawaban Anda :)urllib.urlopen()
akan memanggil soket jaringan, menunggu soket I / O adalah kesempatan bagus untuk mengganti utas dan melakukan hal lain.Iya. :)
Anda memiliki modul ulir tingkat rendah dan modul penguliran tingkat yang lebih tinggi . Tetapi jika Anda hanya ingin menggunakan mesin multicore, modul multiproses adalah cara yang tepat.
Kutipan dari dokumen :
sumber
Threading Diizinkan dengan Python, satu-satunya masalah adalah GIL akan memastikan bahwa hanya satu utas yang dijalankan pada satu waktu (tidak ada paralelisme).
Jadi pada dasarnya jika Anda ingin membuat multi-utas kode untuk mempercepat penghitungan, itu tidak akan mempercepatnya karena hanya satu utas yang dijalankan pada satu waktu, tetapi jika Anda menggunakannya untuk berinteraksi dengan database misalnya, itu akan.
sumber