Вывод прогресс-бара в Python с multiprocessing и tqdm
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Погрузимся в параллельное выполнение задач! Примените tqdm
в многопроцессорных приложениях с использованием общих ресурсов для визуализации прогресса. Вот как это выглядит:
from multiprocessing import Process, Manager, Lock
from tqdm import tqdm
def worker(counter, lock):
with lock:
counter.value += 1
if __name__ == "__main__":
manager = Manager()
counter = manager.Value('i', 0)
lock = Lock()
workers = 10
with tqdm(total=workers) as progress_bar:
processes = [Process(target=worker, args=(counter, lock)) for _ in range(workers)]
for process in processes:
process.start()
while any(process.is_alive() for process in processes):
progress_bar.update(n=counter.value – progress_bar.n)
for process in processes:
process.join()
Данный код обновляет индикатор прогресса tqdm
в реальном времени по мере увеличения значения счётчика рабочими процессами. Не обязательно использовать time.sleep()
— мы же не в отпуске!
Когда следует использовать multiprocessing.Pool imap, imap_unordered?
С помощью multiprocessing
, а именно Pool.imap
или Pool.imap_unordered
, вы сможете полностью задействовать CPU. Разберёмся, в чём их специфика.
Упорядоченный прогресс с imap
imap
— это версия функции map
, адаптированная для многопроцессорности, которая возвращает результаты стриктно по порядку. Её интеграция с tqdm
выглядит так:
from multiprocessing import Pool
from tqdm import tqdm
def heavy_lifter(x):
return x * x
if __name__ == '__main__':
pool_size = 4
tasks = range(1000)
with Pool(pool_size) as pool:
results = list(tqdm(pool.imap(heavy_lifter, tasks), total=len(tasks)))
Быстрый результат с imap_unordered
В свою очередь imap_unordered
возвращает результаты по мере их выполнения, не учитывая исходный порядок.
results = list(tqdm(pool.imap_unordered(heavy_lifter, tasks), total=len(tasks)))
Ускорение индикатора прогресса с помощью process_map
Функция process_map
из модуля tqdm.contrib.concurrent
позволяет удобно отслеживать прогресс выполнения ваших задач.
from tqdm.contrib.concurrent import process_map
results = process_map(heavy_lifter, tasks, max_workers=pool_size, chunksize=10)
Для работы требуется версия tqdm
4.42.0 или более новая. Не забывайте об обновлениях!
Подводные камни и способы их устранения
Вот несколько ключевых моментов для успешного использования многопроцессорности:
Выбор между порядком и скоростью
Применяйте imap
для последовательности, imap_unordered
— для скорости.
Особенности оценки времени
С imap_unordered
время выполнения может оказаться непредсказуемым.
Подходящий инструмент для задачи
Используйте различные методы класса Pool
, наиболее подходящие для вашей задачи.
Корректное завершение работы
Используйте Pool
в контекстном менеджере для правильного освобождения ресурсов после завершения задач.
Визуализация
Представьте, что ваш код – это поезд, где каждая задача – это вагон. Каждый процесс – это локомотив, тянущий за собой ряд своих задач.
from multiprocessing import Pool
from tqdm import tqdm
with Pool(processes=4) as pool:
r = list(tqdm(pool.imap_unordered(func, tasks), total=len(tasks)))
Расширение возможностей с помощью сторонних библиотек
Не ограничивайтесь стандартной библиотекой. Используйте всё разнообразие доступных инструментов.
Знакомтесь: p_tqdm
p_tqdm
удобно комбинирует многопроцессорность и визуализацию прогресса. Следите за обновлениями на GitHub!
Работа с Chunksize
Chunksize
– мощный инструмент для эффективной настройки производительности вашей программы.
Непрерывное развитие
Следите за обновлениями tqdm
. Даже малейшие изменения могут значительно улучшить работу.
Полезные материалы
- GitHub – tqdm/tqdm
- multiprocessing – Python 3.12.2 Documentation
- tqdm.tqdm – Документация tqdm
- Real Python – Полное руководство по многопроцессорности
- concurrent.futures – Python 3.12.2 Documentation
- Beginner's Guide to Concurrency and Parallelism in Python – Toptal®
- Python Multiprocessing Tutorial: Run Code in Parallel Using the Multiprocessing Module – YouTube