Python 3'te çoklu işlem ile çoklu okuma ve asyncio karşılaştırması


123

Python 3.4'te çoklu işlem / iş parçacığı için birkaç farklı kitaplık olduğunu buldum: çoklu işlem , iş parçacığı ve asyncio .

Ama hangisini kullanacağımı veya "önerilen" olduğunu bilmiyorum. Aynı şeyi mi yapıyorlar yoksa farklılar mı? Varsa hangisi ne için kullanılıyor? Bilgisayarımda çok çekirdekli bir program yazmak istiyorum. Ama hangi kütüphaneyi öğrenmem gerektiğini bilmiyorum.


Yanıtlar:


86

(Biraz) farklı amaçlara ve / veya gereksinimlere yöneliktirler. CPython (tipik, ana hat Python uygulaması) hala global yorumlayıcı kilidine sahiptir, bu nedenle çok iş parçacıklı bir uygulama (günümüzde paralel işlemeyi gerçekleştirmenin standart bir yolu) yetersizdir. Bu yüzden tercih multiprocessing edilebilirthreading . Ancak her sorun etkin bir şekilde [neredeyse bağımsız] parçalara ayrılamayabilir, bu nedenle süreçler arası yoğun iletişime ihtiyaç olabilir. Bu yüzden genel multiprocessingolarak tercih edilmeyebilir threading.

asyncio(bu teknik yalnızca Python'da mevcut değildir, diğer diller ve / veya çerçevelerde de vardır, örneğin Boost.ASIO ) paralel kod yürütme ihtiyacı olmadan birçok eşzamanlı kaynaktan çok sayıda G / Ç işlemini etkin bir şekilde gerçekleştirme yöntemidir. . Bu nedenle, genel olarak paralel işlem için değil, belirli bir görev için yalnızca bir çözüm (gerçekten iyi bir çözüm!).


7
Üçünün de paralellik sağlayamayabilirken, hepsinin eşzamanlı (engellemeyen) görevler yapabileceklerine dikkat edin.
sargas

78

TL; DR

Doğru Seçimi Yapmak:

En popüler eşzamanlılık biçimlerini inceledik. Ancak soru hala var - hangisini ne zaman seçmelisiniz? Gerçekten kullanım durumlarına bağlıdır. Deneyimlerime (ve okumaya) göre, bu sözde kodu takip etme eğilimindeyim:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • CPU Bound => Çoklu İşlem
  • G / Ç Bağlantısı, Hızlı G / Ç, Sınırlı Bağlantı Sayısı => Çoklu İş Parçacığı
  • I / O Bound, Slow I / O, Birçok bağlantı => Asyncio

Referans


[ NOT ]:

  • Uzun bir arama yönteminiz varsa (yani, uyku süresi veya tembel G / Ç içeren bir yöntem), en iyi seçim eşzamanlılık olarak tek bir iş parçacığı ile çalışan asyncio , Twisted veya Tornado yaklaşımıdır (coroutine yöntemleri).
  • asyncio , Python3.4 ve sonrasında çalışır .
  • Tornado ve Twisted , Python2.7'den beri hazır
  • uvloop ultra hızlı asyncioolay döngüsüdür ( uvloopasyncio 2-4 kat daha hızlı hale getirir ).

[GÜNCELLEME (2019)]:

  • Japranto ( GitHub ) , uvloop tabanlı çok hızlı bir ardışık düzen HTTP sunucusudur .

Öyleyse, talep etmem gereken bir url listem varsa, Asyncio kullanmak daha mı iyi ?
mingchau

1
@mingchau, Evet, ancak unutmayın, asynciobeklenebilir işlevlerden kullandığınızda kullanabilirsiniz, requestkitaplık, aiohttpkitaplık veya zaman uyumsuz istek vb. gibi kullanmak yerine, beklenebilir bir yöntem değildir .
Benyamin Jafari

multithread veya asyncio gitmek için lütfen slowIO ve fastIO'yu uzatın>?
qrtLs

1
Lütfen io_very_slow
değişken

1
@variable I / O bound, programınızın zamanının çoğunu ağ bağlantısı, sabit sürücü, yazıcı veya uyku süreli bir olay döngüsü gibi yavaş bir cihazla konuşarak geçirdiği anlamına gelir. Bu nedenle, engelleme modunda, iş parçacığı veya asyncio arasında seçim yapabilirsiniz ve sınırlayıcı bölümünüz çok yavaşsa, işbirliğine dayalı çoklu görev (asyncio) daha iyi bir seçimdir (yani kaynak açlığından, ölü kilitlerden ve yarış koşullarından kaçınmak)
Benyamin Jafari

10

Temel fikir bu:

Öyle mi IO bağlı veri? ---------> KULLANasyncio

ÖYLE İşlemci -AĞIR? -----> KULLANmultiprocessing

BAŞKA ? ----------------------> KULLANthreading

Dolayısıyla, IO / CPU problemleriniz olmadıkça temelde iş parçacığı oluşturmaya devam edin.


5

Gelen çoklu işlem size hesaplamalar dağıtmak için birden fazla CPU kaldıraç. CPU'ların her biri paralel çalıştığından, aynı anda birden fazla görevi etkili bir şekilde çalıştırabilirsiniz. CPU'ya bağlı görevler için çoklu işlemeyi kullanmak isteyebilirsiniz . Bir örnek, büyük bir listenin tüm öğelerinin toplamını hesaplamaya çalışıyor olabilir. Makinenizde 8 çekirdek varsa, listeyi daha küçük 8 listeye "bölebilir" ve bu listelerin her birinin toplamını ayrı çekirdekte ayrı ayrı hesaplayabilir ve ardından bu sayıları toplayabilirsiniz. Bunu yaparak ~ 8x hızlanma elde edeceksiniz.

(Çoklu) iş parçacığı içindebirden fazla CPU'ya ihtiyacınız yok. Web'e çok sayıda HTTP isteği gönderen bir program hayal edin. Tek iş parçacıklı bir program kullandıysanız, her istekte yürütmeyi (blok) durdurur, bir yanıt bekler ve bir yanıt alır almaz devam eder. Buradaki sorun, CPU'nuzun işi yapmasını bazı harici sunucuları beklerken gerçekten çalışmıyor olmasıdır; bu arada gerçekten bazı yararlı işler yapabilirdi! Düzeltme, iş parçacığı kullanmaktır - her biri web'den bazı içerik talep etmekten sorumlu olan birçoğunu oluşturabilirsiniz. İş parçacıklarıyla ilgili güzel olan şey, bir CPU üzerinde çalışsalar bile, CPU'nun zaman zaman bir iş parçacığının yürütülmesini "dondurması" ve diğerini yürütmeye atlamasıdır (buna bağlam değiştirme denir ve bu, deterministik olmayan aralıklar). - iplik kullanın.

asyncio , esasen CPU'nun değil, bir programcı (veya aslında uygulamanızın) olarak, bağlam anahtarının nerede ve ne zaman olacağına karar verirseniz, iş parçacığıdır . Python'da await, eşliğinizin yürütülmesini askıya almak için bir anahtar sözcük kullanırsınız ( asyncanahtar sözcük kullanılarak tanımlanır ).


Birden çok iş parçacığım varsa ve yanıtları daha hızlı almaya başlarsam - ve yanıtlardan sonra işim daha CPU'ya bağlıysa - sürecim birden çok çekirdeği kullanır mı? Yani, birden çok çekirdek kullanmak yerine iş parçacıkları dondurur mu?
aspiring 1

Soruyu anladığımdan emin değilim. Yanıtlar hızlandığında birden çok çekirdek kullanmanız gerekip gerekmediğiyle mi ilgili? Durum buysa - yanıtların ne kadar hızlı olduğuna ve CPU kullanmaya kıyasla onları beklerken gerçekten ne kadar zaman harcadığınıza bağlıdır. Zamanınızın çoğunu CPU yoğun görevlerle geçiriyorsanız, birden fazla çekirdeğe (mümkünse) dağıtmak faydalı olacaktır. Ve eğer sistemin işini "gerçekleştirdikten" sonra kendiliğinden paralel işlemeye geçip geçmeyeceği sorusu CPU'ya bağlıdır - öyle düşünmüyorum - genellikle bunu yapması için açıkça söylemeniz gerekir.
Tomasz Bartkowiak

Kullanıcıların chatbot mesajlarının sunucuya gönderildiği ve yanıtların sunucu tarafından POST isteği kullanılarak geri gönderildiği bir chatbot uygulaması düşünüyordum. Bunun daha çok CPU yoğun bir görev olduğunu düşünüyor musunuz, çünkü gönderilen ve alınan yanıt json olabilir, ancak şüpheliydim - kullanıcı yanıtını yazmak için zaman alırsa ne olur, bu yavaş bir G / Ç örneği mi? (kullanıcı geç yanıt gönderiyor)
aspiring1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.