MPI + tqdm - обновление прогрессбара только из одного процесса

У меня есть сценарий, настроенный для одновременной работы с mpiexec с несколькими процессами. Я использую mpi4py для управления вещами MPI из python. Мне также очень нравится tqdm для индикаторов выполнения. Проблема в том, что несколько процессов могут сломать tqdm всеми возможными способами, потому что несколько экземпляров печатают на один и тот же экран.

Есть ли способ указать tqdm печатать обновления только при определенных условиях? Я ищу что-то вроде следующего:

from mpi4py import MPI
from tqdm import trange
from time import sleep

t = trange(10)
for i in t:
    sleep(0.5)
    if MPI.COMM_WORLD.rank == 0:
        t.update_progress()  # <--- Not working, but I want this.

person Bendik    schedule 23.05.2019    source источник


Ответы (2)


Да, вы, вероятно, ищете что-то в строках:

pbar = tqdm.tqdm(total = len(inputs))
for i in t:
    if something_with_i:
         pbar.update(1)
person sdgaw erzswer    schedule 05.08.2019
comment
Pbar не будет унаследован подпроцессом в mpi4py. - person Zézouille; 15.12.2019

Вот правильный ответ:

https://stackoverflow.com/a/36094541/9217178

Вставляю свои 2 цента:

from tqdm import tqdm
from mpi4py import MPI

communicator = MPI.COMM_WORLD
rank = communicator.Get_rank()
nb_process = communicator.Get_size()
total = 100
compute_tag = 0
end_tag = 99

if rank == 0:
    # rank 0 is the master node to update progress bar
    pbar = tqdm(total=total)
    update_msg = None

else:
    update_msg = None

#******************************************************************* I'm a Barrier
communicator.Barrier()
if rank == 0:

    remaining = nb_process - 1
    while remaining > 0:
        s = MPI.Status()
        communicator.Probe(status=s)
        if s.tag == compute_tag:
            update_msg = communicator.recv(tag=compute_tag)  
            #note: send/recv for basic python instances and Send/Recv for numpy array

            # only master to update pbar
            pbar.update(1)
        elif s.tag == end_tag:
            update_msg = communicator.recv(tag=end_tag)

            # remaining drops to 0, loop ends
            remaining -= -1
            print('remaining: {}', remaining)

else:
    for i in range(10):
        #compute something and send a message to master node (rank 0)
        communicator.send(update_msg, dest=0, tag=compute_tag)

    # when this node ends send a eng_tag message
    communicator.send(update_msg, tag=end_tag)
person Zézouille    schedule 15.12.2019