Multiprocessamento em Python: execução de processos em paralelo
O multiprocessamento Python permite dividir a carga de trabalho em vários processos e, assim, reduzir o tempo total de execução. Isso representa uma grande vantagem, especialmente quando é necessário realizar muitos cálculos ou quando há grandes conjuntos de dados.
O que é multiprocessamento Python?
O multiprocessamento em Python refere-se à capacidade de executar vários processos ao mesmo tempo para aproveitar ao máximo o desempenho dos sistemas com múltiplos núcleos. Ao contrário dos sistemas de thread único, nos quais as tarefas são executadas sequencialmente, o multiprocessamento permite que diferentes partes do programa sejam executadas em paralelo e independentemente. Cada processo tem o seu próprio espaço de memória e pode ser processado em núcleos de processador separados, o que reduz significativamente o tempo de execução para operações que exigem muitos cálculos ou têm requisitos de tempo rigorosos.
O multiprocessamento Python pode ser utilizado no processamento e análise de dados, por exemplo, para processar grandes conjuntos de dados de forma mais rápida. Também pode ser usado em simulações e cálculos de modelagem, como em aplicações científicas, para reduzir os tempos de execução de cálculos complexos. Além disso, o multiprocessamento é usado na área de web scraping para coletar dados de várias páginas da web simultaneamente, bem como no processamento de imagens e visão computacional para melhorar a eficiência das operações de análise.
Onde é possível implementar o multiprocessamento em Python?
Python oferece várias possibilidades para implementar o multiprocessamento. A seguir, apresentamos três ferramentas comuns: o módulo multiprocessing, a biblioteca concurrent.futures e o pacote joblib.
O módulo multiprocessing
Multiprocessing é o módulo padrão para multiprocessamento em Python. Com ele, é possível criar processos, trocar dados entre esses processos e realizar sincronizações por meio de bloqueios, filas e outros mecanismos.
import multiprocessing
def task(n):
result = n * n
print(f"Result: {result}")
if __name__ == "__main__":
processes = []
for i in range(1, 6):
process = multiprocessing.Process(target=task, args=(i,))
processes.append(process)
process.start()
for process in processes:
process.join()pythonNo exemplo anterior, a classe multiprocessing.Process foi usada para criar e iniciar processos que executam a função task(). Essa função pega o número transferido e o eleva ao quadrado. Em seguida, cada processo é iniciado e aguarda-se que eles terminem antes de continuar com o programa principal. O resultado é obtido com uma f-string, que é um método do Python string format para ligar expressões. A sequência de saída dos resultados não segue uma ordem específica e pode variar em cada execução.
Você também pode criar um pool de processos com Python multiprocessing da seguinte maneira:
import multiprocessing
def task(n):
return n * n
if __name__ == "__main__":
with multiprocessing.Pool() as pool:
results = pool.map(task, range(1, 6))
print(results) # Output: [1, 4, 9, 16, 25]pythonCom pool.map(), a função task() é aplicada a uma sequência de dados, e os resultados são recolhidos e devolvidos.
A biblioteca concurrent.futures
O módulo concurrent.futures fornece uma interface de alto nível para a execução assíncrona e o processamento paralelo de tarefas. Ele usa o Pool Executor para executar tarefas num pool de processos ou threads. Este módulo oferece uma maneira mais simples de lidar com tarefas assíncronas e, em muitos casos, é mais fácil de usar do que o módulo multiprocessing do Python.
import concurrent.futures
def task(n):
return n * n
with concurrent.futures.ProcessPoolExecutor() as executor:
futures = [executor.submit(task, i) for i in range(1, 6)]
for future in concurrent.futures.as_completed(futures):
print(future.result()) # result in random orderpythonO código utiliza o módulo concurrent.futures para processar tarefas em paralelo com o ProcessPoolExecutor. A função task(n) é transferida para os números de 1 a 5. O método as_completed() aguarda a conclusão das tarefas e retorna os resultados em ordem aleatória.
joblib
joblib é uma biblioteca externa do Python concebida para simplificar o processamento em paralelo, por exemplo, para tarefas repetitivas como executar funções com diferentes parâmetros de entrada ou trabalhar com grandes quantidades de dados. As principais funções do joblib são paralelizar tarefas, armazenar em cache os resultados das funções e otimizar os recursos de memória e computação.
from joblib import Parallel, delayed
def task(n):
return n * n
results = Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))
print(results) # Output: Results of the function for numbers from 1 to 10pythonCom a expressão Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11)), inicia-se a execução em paralelo da função task() para os números de 1 a 10. Parallel está configurado com o argumento n_jobs=4, o que indica que podem ser processados até quatro trabalhos em paralelo. Ao chamar delayed(task)(i), cria-se a tarefa que deve ser executada em paralelo para cada número i no intervalo de 1 a 10. Ou seja, a função task() é chamada simultaneamente para cada um desses números. O resultado para os números de 1 a 10 é armazenado em results e impresso.