multiprocessamento vs multithreading vs asyncio em Python 3


105

Descobri que no Python 3.4 existem poucas bibliotecas diferentes para multiprocessamento / threading: multiprocessamento vs threading vs asyncio .

Mas não sei qual usar ou é o "recomendado". Eles fazem a mesma coisa ou são diferentes? Em caso afirmativo, qual é usado para quê? Quero escrever um programa que use multicores no meu computador. Mas não sei qual biblioteca devo aprender.


Respostas:


79

Eles são destinados a finalidades e / ou requisitos (ligeiramente) diferentes. CPython (uma implementação típica do Python principal) ainda tem o bloqueio do interpretador global, então um aplicativo multi-threaded (uma forma padrão de implementar processamento paralelo atualmente) é subótimo. É por isso que multiprocessing pode ser preferível threading. Mas nem todo problema pode ser efetivamente dividido em partes [quase independentes], portanto, pode haver uma necessidade de comunicações inter-processos pesadas. É por isso multiprocessingque não pode ser preferido threadingem geral.

asyncio(esta técnica está disponível não apenas em Python, outras linguagens e / ou frameworks também a têm, por exemplo, Boost.ASIO ) é um método para lidar com muitas operações de I / O de muitas fontes simultâneas sem a necessidade de execução paralela de código . Portanto, é apenas uma solução (boa mesmo!) Para uma tarefa específica, não para o processamento paralelo em geral.


7
Observando que, embora os três possam não atingir o paralelismo, todos eles são capazes de realizar tarefas simultâneas (sem bloqueio).
sargas

65

[Resposta rápida]

TL; DR

Fazendo a escolha certa:

Percorremos as formas mais populares de simultaneidade. Mas a questão permanece - quando devo escolher qual? Realmente depende dos casos de uso. Pela minha experiência (e leitura), tendo a seguir este pseudo código:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • Limite de CPU => Multiprocessamento
  • I / O Bound, Fast I / O, Limited Number of Connections => Multi Threading
  • Limite de E / S, E / S lento, Muitas conexões => Asyncio

Referência


[ NOTA ]:

  • Se você tiver um método de chamada longa (ou seja, um método que contenha um tempo de sono ou I / O preguiçoso), a melhor escolha é asyncio , abordagem Twisted ou Tornado (métodos de co-rotina), que funcionam com uma única thread como simultaneidade.
  • asyncio funciona em Python3.4 e posterior.
  • Tornado e Twisted estão prontos desde Python 2.7
  • uvloop é asyncioum loop de eventos ultrarrápido ( uvloop torna asyncio2-4x mais rápido).

[ATUALIZAÇÃO (2019)]:

  • Japranto ( GitHub ) é um servidor HTTP de pipeline muito rápido baseado em uvloop .

Então, se eu tiver uma lista de urls para solicitar, é melhor usar o Asyncio ?
1919 de mingchau

1
@mingchau, Sim, mas lembre-se de que você pode usar desde asyncioquando usar funções em espera, requestbiblioteca não é um método em espera, em vez de usar como a aiohttpbiblioteca ou solicitação assíncrona e etc.
Benyamin Jafari

estenda slowIO e fastIO para multithread ou asyncio>?
qrtLs

@qrtLs Quando você tem um SlowIO, o AsyncIO é muito útil e mais eficiente.
Benyamin Jafari

1
@variable I / O bound significa que seu programa passa a maior parte do tempo conversando com um dispositivo lento, como uma conexão de rede, um disco rígido, uma impressora ou um loop de evento com tempo de espera. Portanto, no modo de bloqueio, você pode escolher entre threading ou assíncio e, se sua seção delimitadora for muito lenta, multitarefa cooperativa (assíncio) é uma escolha melhor (ou seja, evitar a falta de recursos, bloqueios mortos e condições de corrida)
Benyamin Jafari

8

Esta é a ideia básica:

É IO -BOUND? ---------> USEasyncio

É CPU PESADO? -----> USEmultiprocessing

OUTRO ? ----------------------> USEthreading

Então, basicamente, mantenha o threading, a menos que você tenha problemas de E / S / CPU.


0

No multiprocessamento, você aproveita várias CPUs para distribuir seus cálculos. Como cada uma das CPUs funciona em paralelo, você é capaz de executar várias tarefas simultaneamente. Você gostaria de usar multiprocessamento para tarefas vinculadas à CPU . Um exemplo seria tentar calcular a soma de todos os elementos de uma lista enorme. Se sua máquina tiver 8 núcleos, você pode "cortar" a lista em 8 listas menores e calcular a soma de cada uma dessas listas separadamente em núcleos separados e, em seguida, apenas somar esses números. Você obterá uma aceleração de ~ 8x ao fazer isso.

Em threadingvocê não precisa de múltiplas CPUs. Imagine um programa que envia muitas solicitações HTTP para a web. Se você usasse um programa de thread único, ele interromperia a execução (bloco) a cada solicitação, aguardaria uma resposta e, em seguida, continuaria assim que recebesse uma resposta. O problema aqui é que sua CPU não está realmente funcionando enquanto espera que algum servidor externo faça o trabalho; ele poderia realmente ter feito algum trabalho útil nesse ínterim! A solução é usar threads - você pode criar muitos deles, cada um responsável por solicitar algum conteúdo da web. A coisa boa sobre threads é que, mesmo se eles rodarem em uma CPU, a CPU de vez em quando "congela" a execução de uma thread e pula para a execução da outra (é chamada de troca de contexto e acontece constantemente em não determinística intervalos). - use threading.

asyncio é essencialmente threading onde não a CPU, mas você, como um programador (ou na verdade sua aplicação), decide onde e quando a troca de contexto acontece . Em Python, você usa uma awaitpalavra-chave para suspender a execução de sua co-rotina (definida usando a asyncpalavra-chave).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.