multiprocessing vs multithreading vs asyncio dengan Python 3

108

Saya menemukan bahwa di Python 3.4 ada beberapa perpustakaan yang berbeda untuk multiprocessing / threading: multiprocessing vs threading vs asyncio .

Tapi saya tidak tahu mana yang akan digunakan atau yang "direkomendasikan". Apakah mereka melakukan hal yang sama atau berbeda? Jika iya, mana yang digunakan untuk apa? Saya ingin menulis program yang menggunakan multicores di komputer saya. Tapi saya tidak tahu perpustakaan mana yang harus saya pelajari.

user3654650
sumber
1
Mungkin aku terlalu bodoh untuk bantuan AsyncIO
Martin Thoma

Jawaban:

82

Mereka ditujukan untuk tujuan dan / atau persyaratan yang (sedikit) berbeda. CPython (tipikal, implementasi Python jalur utama) masih memiliki kunci interpreter global sehingga aplikasi multi-threaded (cara standar untuk mengimplementasikan pemrosesan paralel saat ini) menjadi suboptimal. Itulah mengapa multiprocessing mungkin lebih disukai threading. Tetapi tidak setiap masalah dapat secara efektif dipecah menjadi bagian-bagian [hampir independen], jadi mungkin ada kebutuhan dalam komunikasi antarproses yang berat. Itu sebabnya multiprocessingmungkin tidak disukai daripada threadingsecara umum.

asyncio(teknik ini tersedia tidak hanya di Python, bahasa dan / atau kerangka kerja lain juga memilikinya, misalnya Boost.ASIO ) adalah metode untuk secara efektif menangani banyak operasi I / O dari banyak sumber secara bersamaan tanpa perlu eksekusi kode paralel . Jadi ini hanya solusi (yang memang bagus!) Untuk tugas tertentu, bukan untuk pemrosesan paralel pada umumnya.

pengguna3159253
sumber
7
Memperhatikan bahwa sementara ketiganya mungkin tidak mencapai paralelisme, mereka semua mampu melakukan tugas bersamaan (non-pemblokiran).
sargas
68

[Jawaban cepat]

TL; DR

Membuat Pilihan yang Tepat:

Kami telah menelusuri bentuk konkurensi yang paling populer. Tetapi pertanyaannya tetap - kapan harus memilih yang mana? Itu sangat tergantung pada kasus penggunaan. Dari pengalaman saya (dan membaca), saya cenderung mengikuti kode pseudo ini:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • CPU Terikat => Multi Pemrosesan
  • I / O Bound, Fast I / O, Jumlah Koneksi Terbatas => Multi Threading
  • I / O Terikat, I / O Lambat, Banyak koneksi => Asyncio

Referensi


[ CATATAN ]:

  • Jika Anda memiliki metode panggilan lama (yaitu metode yang berisi waktu tidur atau I / O malas), pilihan terbaik adalah asyncio , pendekatan Twisted atau Tornado (metode coroutine), yang bekerja dengan satu thread sebagai konkurensi.
  • asyncio bekerja pada Python3.4 dan yang lebih baru.
  • Tornado dan Twisted sudah siap sejak Python2.7
  • uvloop adalah asyncioevent loop yang sangat cepat ( uvloop membuat asyncio2-4x lebih cepat).

[PEMBARUAN (2019)]:

  • Japranto ( GitHub ) adalah server HTTP pipelining yang sangat cepat berdasarkan uvloop .
Benyamin Jafari
sumber
Jadi, jika saya memiliki daftar url untuk diminta, lebih baik gunakan Asyncio ?
mingchau
1
@mingchau, Ya, tetapi perlu diingat, Anda dapat menggunakan dari asynciosaat Anda menggunakan dari fungsi yang menunggu, requestperpustakaan bukanlah metode yang dapat menunggu, alih-alih Anda dapat menggunakan seperti aiohttpperpustakaan atau async-request dan lain
Benyamin Jafari
harap perpanjang pada slowIO dan fastIO untuk menggunakan multithread atau asyncio>?
qrtLs
1
Tolong bisakah Anda memberi tahu apa sebenarnya io_very_slow
variabel
1
@variable I / O bound berarti program Anda menghabiskan sebagian besar waktunya untuk berbicara dengan perangkat yang lambat, seperti koneksi jaringan, hard drive, printer, atau event loop dengan waktu tidur. Jadi dalam mode pemblokiran, Anda dapat memilih antara threading atau asyncio, dan jika bagian pembatas Anda sangat lambat, multitasking kooperatif (asyncio) adalah pilihan yang lebih baik (yaitu menghindari kelaparan sumber daya, jalan buntu, dan kondisi balapan)
Benyamin Jafari
8

Ini adalah ide dasarnya:

Apakah IO -BOUND? ---------> GUNAKANasyncio

APAKAH ITU CPU BERAT? -----> GUNAKANmultiprocessing

LAIN ? ----------------------> GUNAKANthreading

Jadi pada dasarnya tetap berpegang pada threading kecuali Anda memiliki masalah IO / CPU.

Farsheed
sumber
0

Dalam multiprosesing Anda memanfaatkan banyak CPU untuk mendistribusikan perhitungan Anda. Karena masing-masing CPU berjalan secara paralel, Anda secara efektif dapat menjalankan banyak tugas secara bersamaan. Anda ingin menggunakan multiprocessing untuk CPU-terikat tugas tugas yang . Contohnya adalah mencoba menghitung jumlah semua elemen dari daftar besar. Jika mesin Anda memiliki 8 inti, Anda dapat "memotong" daftar menjadi 8 daftar yang lebih kecil dan menghitung jumlah masing-masing daftar tersebut secara terpisah pada inti terpisah dan kemudian menjumlahkan angka-angka itu. Anda akan mendapatkan kecepatan ~ 8x dengan melakukan itu.

Dalam - penggunaan threading. threadingAnda tidak membutuhkan banyak CPU. Bayangkan sebuah program yang mengirimkan banyak permintaan HTTP ke web. Jika Anda menggunakan program single-threaded, itu akan menghentikan eksekusi (blok) di setiap permintaan, menunggu respons, dan kemudian melanjutkan setelah menerima respons. Masalahnya di sini adalah bahwa CPU Anda tidak benar-benar berfungsi sambil menunggu server eksternal melakukan pekerjaan itu; itu sebenarnya bisa melakukan beberapa pekerjaan berguna untuk sementara waktu! Cara mengatasinya adalah dengan menggunakan utas - Anda dapat membuat banyak utas, masing-masing bertanggung jawab untuk meminta beberapa konten dari web. Hal yang menyenangkan tentang utas adalah, meskipun mereka berjalan pada satu CPU, CPU dari waktu ke waktu "membekukan" eksekusi satu utas dan melompat untuk mengeksekusi utas lainnya (ini disebut pengalihan konteks dan itu terjadi terus-menerus pada non-deterministik interval).

asyncio pada dasarnya adalah threading di mana bukan CPU tetapi Anda, sebagai programmer (atau sebenarnya aplikasi Anda), memutuskan di mana dan kapan peralihan konteks terjadi . Di Python, Anda menggunakanawait kata kunci untuk menangguhkan eksekusi coroutine Anda (ditentukan menggunakan asynckata kunci).

Tomasz Bartkowiak
sumber