багатопроцесорність проти багатопоточності проти asyncio в Python 3


107

Я виявив, що в Python 3.4 існує декілька різних бібліотек для багатопроцесорної обробки / потокової роботи: багатопроцесорність проти потоків проти asyncio .

Але я не знаю, який із них використовувати, чи є «рекомендованим». Вони роблять одне і те ж, або відрізняються? Якщо так, який для чого використовується? Я хочу написати програму, яка використовує багатоядерні системи на моєму комп’ютері. Але я не знаю, яку бібліотеку мені слід вивчити.


Відповіді:


81

Вони призначені для (трохи) різних цілей та / або вимог. CPython (типова основна реалізація Python) все ще має глобальний блокувальник інтерпретатора, тому багатопотокове додаток (стандартний спосіб реалізації паралельної обробки в наш час) є неоптимальним. Саме тому multiprocessing може бути краще threading. Але не кожна проблема може бути ефективно розділена на [майже незалежні] частини, тому може виникнути потреба у важких міжпроцесорних комунікаціях. Ось чому, multiprocessingможливо, не перевагу над threadingзагалом.

asyncio(ця техніка доступна не лише в Python, її також мають інші мови та / або фреймворки, наприклад Boost.ASIO ) - це метод для ефективної обробки багатьох операцій вводу-виводу з багатьох одночасних джерел без необхідності паралельного виконання коду . Тож це просто рішення (справді хороше!) Для конкретного завдання, а не для паралельної обробки загалом.


7
Відзначаючи, що хоча всі троє не можуть досягти паралелізму, всі вони здатні виконувати паралельні (неблокуючі) завдання.
саргас

68

[Швидка відповідь]

TL; DR

Правильний вибір:

Ми пройшли через найпопулярніші форми паралелізму. Але питання залишається - коли слід вибрати, який? Це насправді залежить від випадків використання. З мого досвіду (і читання) я схильний слідувати цьому псевдокоду:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • Прив'язка процесора => Багатопроцесорне
  • Обмежений ввід / вивід, швидкий ввід / вивід, обмежена кількість з'єднань => Багатопотокові
  • Зв'язок вводу-виводу, повільний введення-виведення, багато з'єднань => Asyncio

Довідково


[ ПРИМІТКА ]:

  • Якщо у вас є метод тривалого виклику (тобто метод, який містить час сну або ледачий ввід / вивід), найкращим вибором буде підхід asyncio , Twisted або Tornado (спільні методи), який працює з одним потоком як паралельність.
  • asyncio працює на Python3.4 та пізніших версіях.
  • Tornado і Twisted готові з Python2.7
  • uvloop - це надшвидкий asyncioцикл подій ( uvloop робить в asyncio2-4 рази швидше).

[ОНОВЛЕННЯ (2019)]:

  • Japranto ( GitHub ) - це дуже швидкий конвеєрний HTTP-сервер, заснований на uvloop .

Отже, якщо у мене є список URL-адрес для запиту, краще використовувати Asyncio ?
mingchau

1
@mingchau, так, але майте на увазі, ви можете використовувати, asyncioколи ви використовуєте з функцій, що очікують, requestбібліотека не є методом, який можна очікувати, замість цього ви можете використовувати такі, як aiohttpбібліотека або асинхронний запит тощо
Бенямін Джафарі

будь ласка, поширте на slowIO і fastIO, щоб перейти до багатопоточності або asyncio>?
qrtLs

@qrtLs Коли у вас SlowIO, AsyncIO дуже корисний і ефективніший.
Benyamin

1
@variable I / O bound означає, що ваша програма проводить більшу частину часу в розмові з повільним пристроєм, таким як мережне підключення, жорсткий диск, принтер або цикл подій із часом сну. Отже, у режимі блокування ви можете вибирати між потоковими потоками або асинсіо, і якщо ваш обмежувальний розділ дуже повільний, спільна багатозадачність (асинціо) є кращим вибором (тобто уникати ресурсів, що вимагають голоду, тупикових ситуацій та умов перегонів)
Беніамін Джафарі

8

Це основна ідея:

Це IO- ЗВ'ЯЗАНИЙ? ---------> ВИКОРИСТАННЯasyncio

ЦЕ CPU -HEAVY? -----> ВИКОРИСТАННЯmultiprocessing

ІНШЕ? ----------------------> ВИКОРИСТАННЯthreading

Отже, в основному дотримуйтесь потоків, якщо у вас немає проблем з введенням / введенням процесора.


0

При багатопроцесорній обробці ви використовуєте кілька процесорів для розподілу своїх розрахунків. Оскільки кожен з центральних процесорів працює паралельно, ви фактично можете виконувати кілька завдань одночасно. Ви хочете використовувати багатопроцесорну обробку для завдань, пов’язаних із процесором . Прикладом може бути спроба обчислити суму всіх елементів величезного списку. Якщо ваша машина має 8 ядер, ви можете "розрізати" список на 8 менших списків і розрахувати суму кожного з цих списків окремо на окремому ядрі, а потім просто скласти ці цифри. Роблячи це, ви досягнете ~ 8-кратного прискорення.

У різьбленнявам не потрібні кілька процесорів. Уявіть собі програму, яка надсилає багато запитів HTTP до Інтернету. Якщо ви використовували однопотокову програму, вона зупиняла б виконання (блокувати) при кожному запиті, чекала відповіді, а потім продовжувала, коли отримала відповідь. Проблема тут полягає в тому, що ваш процесор насправді не виконує роботу, чекаючи, поки якийсь зовнішній сервер виконає цю роботу; тим часом це могло зробити якусь корисну роботу! Виправлення полягає у використанні потоків - ви можете створити багато з них, кожен відповідальний за запит певного вмісту з Інтернету. Приємна річ потоків полягає в тому, що, навіть якщо вони працюють на одному центральному процесорі, процесор час від часу "заморожує" виконання одного потоку і переходить до виконання іншого (це називається перемиканням контексту, і це відбувається постійно на недетермінованих інтервали). - використовувати різьбу.

asyncio - це по суті потоки, де не центральний процесор, а ви як програміст (або насправді ваш додаток) вирішуєте, де і коли відбувається перемикання контексту . У Python ви використовуєте awaitключове слово для призупинення виконання вашої програми (визначеної за допомогою asyncключового слова).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.