multiprocessing
O multiprocessing inicia processos filhos com interpretadores Python separados - a maneira portátil de paralelizar código vinculado à CPU (CPU-bound) em builds Python padrão com GIL. Compartilhe dados via filas (queues), pipes ou multiprocessing.shared_memory.
Receita
from multiprocessing import Pool
def work(n: int) -> int:
return n * n
if __name__ == "__main__":
with Pool() as pool:
print(pool.map(work, range(5)))Quando usar:
- Loops Python puros que consomem muita CPU
- Transformações de dados paralelas entre núcleos
- Isolamento de domínios de falha (o travamento de um worker não afeta todos)
- Contornar o GIL para pipelines de computação
- Tarefas em lote com tarefas independentes
Exemplo de Funcionamento
from multiprocessing import Process, Queue
def producer(q: Queue, count: int) -> None:
for i in range(count):
q.put(i * i)
def consumer(q: Queue) -> None:
items = []
while True:
item = q.get()
if item is None:
break
items.append(item)
print("soma", sum(items))
if __name__ == "__main__":
q: Queue = Queue()
p = Process(target=producer, args=(q, 5))
c = Process(target=consumer, args=(q,))
c.start()
p.start()
p.join()
q.put(None)
c.join()O que isto demonstra:
Queuepassa objetos serializáveis (picklable) entre processos- O sentinela
Noneencerra o loop do consumidor if __name__ == "__main__"é necessário para o método de inicializaçãospawn(macOS, Windows)- Processos não compartilham objetos na memória por padrão
Aprofundamento
Métodos de Inicialização
| Método | Comportamento |
|---|---|
| spawn | Novo interpretador (padrão macOS/Win) |
| fork | Copia o processo pai (Unix, cuidado com threads) |
Opções de IPC (Comunicação Interprocessos)
Queue,Pipepara mensagensshared_memorypara arrays grandes (a partir do Python 3.8)- Prefira passar snapshots imutáveis em vez de mutação compartilhada
Armadilhas
- Ausência da guarda
main- causa spawn recursivo na importação. Correção:if __name__ == "__main__". - Closures não serializáveis (unpicklable) - o alvo do worker deve ser uma função de nível superior ou serializável. Correção: use
initializer+ funções do módulo. - Serialização de objetos enormes - IPC lento. Correção: use memória compartilhada ou blocos em disco.
fork+ threads - possíveis deadlocks. Correção: prefiraspawnno macOS; inicie os processos antes das threads.- Pool superdimensionado -
memória × workersesgota a RAM. Correção: usemaxtasksperchilde limite o número de workers.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| concurrent.futures.ProcessPoolExecutor | API mais simples | Precisa de primitivas de Processo |
| subprocess (execução única) | Comandos de shell | Execução de muitas funções Python |
| Extensão C / NumPy | Libera o GIL em threads | Loop puro Python intensivo em CPU |
FAQs
Tamanho do Pool?
Comece com os.cpu_count(); reduza se cada tarefa alocar muita memória.
Por que spawn é o padrão no macOS?
É mais seguro com frameworks e o runtime Objective-C do que fork após o início das threads.
Processos podem compartilhar um dict?
Use Manager().dict() - mais lento; prefira passagem de mensagens.
Como fazer log de workers?
Configure o logging no initializer do worker; evite handlers herdados e obsoletos.
Módulo Process vs subprocess?
multiprocessing executa funções Python; subprocess executa executáveis.
maxtasksperchild?
Recicla workers após N tarefas para conter vazamentos de memória em pools longos.
Como cancelar trabalho?
Use shutdown(cancel_futures=True) do Executor (a partir do Python 3.9) ou um sentinela via Queue.
Lambdas são serializáveis?
Não com spawn - use def em nível de módulo.
asyncio substitui multiprocessing?
Não - asyncio é para I/O concorrente; processos são para CPU paralela.
Como fazer benchmark?
Tempo de parede (wall time) com tamanho de payload realista; inclua o overhead de spawn em tarefas curtas.
Relacionados
- concurrent.futures - ProcessPoolExecutor
- O GIL e Python Livre de Threads - por que usar processos
- Queues e Produtor/Consumidor - padrões
- subprocess - comandos externos
Versões da Stack: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.