Estou executando uma computação longa usando multiprocessing.Pool em Python e queria adicionar uma barra de progresso para acompanhá-la. Naturalmente, tentei o tqdm com pool.imap, mas, surpreendentemente, é ~7,3x mais lento do que usar pool.map() sem ele.
Aqui está um exemplo mínimo para reproduzir o problema:
import numpy as np
import time
from multiprocessing import Pool, cpu_count
from functools import partial
from tqdm import tqdm
def dummy_task(step_id, size=500):
data = np.random.randn(size, 3)
dist = np.linalg.norm(data, axis=1)
return step_id, np.min(dist)
if __name__ == "__main__":
steps = list(range(500000)) # Simulate 100 frames
size = 500
print("Running normaly...")
t0 = time.time()
with Pool(processes=cpu_count()) as pool:
results = pool.map(partial(dummy_task, size=size), steps)
t1 = time.time()
pt = t1 - t0
print(f"Time taken: {pt:.3f} seconds\n")
print("Running with tqdm...")
t2 = time.time()
with Pool(processes=cpu_count()) as pool:
results = list(tqdm(pool.imap(partial(dummy_task, size=size), steps), total=len(steps)))
t3 = time.time()
pt_tqm = t3 - t2
print(f"Time taken: {pt_tqm:.3f} seconds")
print (f"Pool Process with TQDM is {pt_tqm/pt:.3f} times slower.")
Há uma pergunta semelhante aqui , de seis anos atrás. Mas não há uma resposta útil. Estou procurando uma maneira de implementar uma barra de progresso ou alguma forma de informação de progresso sem sacrificar a velocidade. Existe alguma maneira de fazer isso?
OBS: Usei apenas o imap no exemplo do tqdm porque não consegui descobrir como usar o mapa com o tqdm.
Sua pergunta vinculada contém a explicação real em uma resposta , que se relaciona à diferença entre mapa e imap, como Paul Smith sugere:
A fragmentação é conhecida por ser crucial para o desempenho em trabalhos leves. Você pode ter certeza de que este resultado não se aplica a
tqdm
.Para adicionar uma barra de progresso sem tornar o cálculo mais lento, defina seu próprio
chunksize
argumento:(Pode haver um tamanho de bloco ideal, mas não testei.)
Para citar o
docs
:1/ Comparar semelhante com semelhante
2/ use unit_scale para evitar ter que contar todos os valores na tela
3/ use chunksize para reduzir as diferenças entre map e imap (crédito @Richard Sheridan)
Funcionando normalmente...
Tempo gasto: 2,151 segundos
Executando com tqdm...
100%|███████████████████████████████████████████████████| 500k/500k [00:02<00:00, 237kit/s]
Tempo gasto: 2,192 segundos
O processo de pool com TQDM é 1,019 vezes mais lento.