[Open source, Python, Параллельное программирование] Визуализируйте многопоточные программы Python с open source инструментом – VizTracer (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Специально к старту нового потока курса Fullstack-разработчик на Python, представляем небольшой авторский обзор кроссплатформенного инструмента визуализации многопоточных программ – VizTracer. У VizTracer 57 форков и 841 звезд на Github. Настраиваемые события, отчёты в HTML, детальная информация о функциях с их исходным кодом, простота применения, отсутствие зависимостей и малый оверхед превращают VizTracer в мастхэв Python-разработчика.Конкурентность – важная часть современного программирования, когда у нас несколько ядер и много задач, которые должны кооперироваться. Однако, когда многопоточные программы не выполняются последовательно, понять их трудно. Инженерам не так-то просто идентифицировать баги и проблемы производительности в таких программах, как это делается в однопоточных программах с одной задачей.В Python вариантов конкурентности много. Самый распространённый, вероятно, – многопоточность, которой добиваются с помощью модуля threading и несколько процессов с помощью модулей myltiprocessing и subprocess, а также недавно появившийся способ – async из модуля asyncio. До появления VizTracer в инструментах, использующих эти техники в целях анализа программ, был пробел.VizTracer – инструмент отслеживания и визуализации написанных на Python программ, который помогает логировать, отлаживать и профилировать код. Хотя он хорошо работает в однопоточных программах с одной задачей, польза от него в смысле конкурентных программ делает инструмент уникальным.Попробуем с простой задачейОпределим, являются ли числа в массиве простыми, и вернём массив логических значений. Вот простое решение:
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
def get_prime_arr(arr):
return [is_prime(elem) for elem in arr]
Выполним его нормально, в один поток, и задействуем VizTracer.
if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for _ in range(6000)]
get_prime_arr(num_arr)
Выполняем команду:
viz_tracer my_program.py
Отчёт стека вызовов показывает, что выполнение кода заняло 140 мс, а большую часть времени заняло выполнение get_prime_arr.
Здесь на каждом элементе массива выполняется функция is_prime. Это ожидаемо и не интересно, если VizTracer вам знаком.Теперь попробуем многопоточную программуСделаем то же самое в программе с несколькими потоками:
if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for i in range(2000)]
thread1 = Thread(target=get_prime_arr, args=(num_arr,))
thread2 = Thread(target=get_prime_arr, args=(num_arr,))
thread3 = Thread(target=get_prime_arr, args=(num_arr,))
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
Чтобы соответствовать рабочей нагрузке однопоточной программы, в коде прописан массив в 2000 элементов на три потока и моделируется ситуация, когда все эти потоки совместно работают над задачей.
Если вы знакомы с Python Global Lock (GIL), то можете ожидать, что программа не станет быстрее: из-за оверхеда она выполняется немного дольше 140 мс, однако можно наблюдать конкурентность множества потоков:
Когда работал один поток (и много раз выполнял функции is_prime), другой поток был заморожен (одна функция is_prime). Позже они поменялись. Это произошло из-за GIL, и причина в том, что в Python нет настоящей многопоточности. Возможна конкурентность, но не параллелизм.Попробуем поработать с multiprocessingЧтобы достичь параллелизма, воспользуемся библиотекой multiprocessing. Вот новая версия кода с применением этой библиотеки:
if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for _ in range(2000)]
p1 = Process(target=get_prime_arr, args=(num_arr,))
p2 = Process(target=get_prime_arr, args=(num_arr,))
p3 = Process(target=get_prime_arr, args=(num_arr,))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
Чтобы запустить его с помощью VizTracer, понадобится дополнительный аргумент:
viztracer --log_multiprocess my_program.py
Вся программа занимает чуть больше 50 мс, задача завершается менее чем за те же 50 мс, то есть программа ускорилась приблизительно втрое. Чтобы сравнить производительность, напишем версию в несколько процессов:
Без GIL множество процессов достигают параллелизма, то есть множество функций is_prime выполняются параллельно.Однако многопоточность в Python не бесполезна. Например, для вычислительно-интенсивных программ и программ с интенсивным вводом-выводом, при помощи sleep можно имитировать задержку ввода-вывода:
def io_task():
time.sleep(0.01)
Попробуем в однопоточной программе с одной задачей:
if __name__ == "__main__":
for _ in range(3):
io_task()
.Вся программа занимает 30 мс; ничего особенного. Теперь воспользуемся многопоточностью:
if __name__ == "__main__":
thread1 = Thread(target=io_task)
thread2 = Thread(target=io_task)
thread3 = Thread(target=io_task)
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
Выполнение занимает 10 мс: ясно, что все потоки работали одновременно и повысили производительность.Теперь поработаем с asyncioВ Python попробовали ввести интересную функциональность – асинхронное программирование. Нашу задачу можно написать асинхронно:
import asyncio
async def io_task():
await asyncio.sleep(0.01)
async def main():
t1 = asyncio.create_task(io_task())
t2 = asyncio.create_task(io_task())
t3 = asyncio.create_task(io_task())
await t1
await t2
await t3
if __name__ == "__main__":
asyncio.run(main())
Поскольку asyncio – буквально однопоточный планировщик с задачами, вы можете использовать VizTracer вместе с этим планировщиком:
Всё те же 10 мс, но большинство отображаемых функций – нижележащая структура, которая, вероятно, не интересует пользователей. Чтобы решить эту проблему, можно использовать --log_async – флаг разделит задачу на части:
viztracer --log_async my_program.py
Теперь задачи пользователя намного яснее. Большую часть времени выполняемых задач нет: единственное, что делает программа, – спит. Вот интересная часть:
На временной шкале показывается, когда задачи создавались и выполнялись. Task-1 была сопрограммой mail(), которая создаёт другие задачи. Задачи 2, 3 и 4 выполняли io_task и sleep, а потом ждали пробуждения. Как показывает график, задачи не перекрывают друг друга, поскольку программа однопоточная, и VizTracer визуализировал её так, чтобы она была понятной. Чтобы сделать код интереснее, добавим вызов time.sleep, чтобы заблокировать асинхронный цикл:
async def io_task():
time.sleep(0.01)
await asyncio.sleep(0.01)
Программа заняла намного больше времени (40 мс) и задачи заняли свои места в асинхронном планировщике. Это поведение очень полезно для диагностики проблем поведения и производительности в асинхронных программах.Смотрите на происходящее с помощью VizTracerПри помощи VizTracer вы видите, что происходит с программой, на временной шкале, а не читаете жалобы из логов. Это помогает лучше понимать вашу конкурентную программу.Исходный код VizTracer открыт под лицензией Apache 2.0, поддерживаются все операционные системы – Linux , MacOS, Windows. Вы можете узнать больше о его функциях и увидеть исходный код в репозитории VizTracer на Github. А освоить разработку на Python и стать Fullstack-разработчиком — на нашем специализированном курсе.
Узнайте, как прокачаться в других специальностях или освоить их с нуля:
Другие профессии и курсыПРОФЕССИИ
- Профессия Fullstack-разработчик на Python
- Профессия Java-разработчик
- Профессия QA-инженер на JAVA
- Профессия Frontend-разработчик
- Профессия Этичный хакер
- Профессия C++ разработчик
- Профессия Разработчик игр на Unity
- Профессия Веб-разработчик
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля
КУРСЫ
- Курс по Machine Learning
- Курс "Machine Learning и Deep Learning"
- Курс "Математика для Data Science"
- Курс "Математика и Machine Learning для Data Science"
- Курс "Python для веб-разработки"
- Курс "Алгоритмы и структуры данных"
- Курс по аналитике данных
- Курс по DevOps
===========
Источник:
habr.com
===========
===========
Автор оригинала: Tian Gao
===========Похожие новости:
- [Open source, Программирование, Геоинформационные сервисы, Визуализация данных, Научно-популярное] Геология XXI века: от реальности к виртуальности
- [Open source, Системное программирование, Реверс-инжиниринг] Linux для macOS M1: что сделала команда Asahi Linux за январь-февраль 2021 (перевод)
- [Программирование, GTK+, Разработка под Linux] Пишем онлайн-радио на языке Vala
- [Разработка веб-сайтов, Программирование, HTML, Лайфхаки для гиков] 5 HTML-трюков, о которых никто не говорит (перевод)
- [Open source, *nix] FOSS News №60 – дайджест материалов о свободном и открытом ПО за 8-14 марта 2021 года
- [Информационная безопасность, Open source, Системное администрирование, GitHub, Разработка под Linux] Эксперты обнаружили критическую уязвимость в подсистеме iSCSI ядра Linux, баг в коде был с 2006 года
- [Python, *nix, C, Разработка под Linux] C и Python: мост между мирами
- [Веб-дизайн, Разработка веб-сайтов, CSS, Программирование] Погружаемся в логические свойства CSS (перевод)
- [Программирование, C++, C, Разработка под Linux] Неблокирующие паттерны: атомарные операции и частичные барьеры памяти (перевод)
- [Python, Java, Разработка под Android, Искусственный интеллект, Flask] Играем с CLIP. Создаем универсальный zero-shot классификатор на Android
Теги для поиска: #_open_source, #_python, #_parallelnoe_programmirovanie (Параллельное программирование), #_skillfactory, #_python, #_programmirovanie (программирование), #_opensourse, #_open_source, #_blog_kompanii_skillfactory (
Блог компании SkillFactory
), #_open_source, #_python, #_parallelnoe_programmirovanie (
Параллельное программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:27
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Специально к старту нового потока курса Fullstack-разработчик на Python, представляем небольшой авторский обзор кроссплатформенного инструмента визуализации многопоточных программ – VizTracer. У VizTracer 57 форков и 841 звезд на Github. Настраиваемые события, отчёты в HTML, детальная информация о функциях с их исходным кодом, простота применения, отсутствие зависимостей и малый оверхед превращают VizTracer в мастхэв Python-разработчика.Конкурентность – важная часть современного программирования, когда у нас несколько ядер и много задач, которые должны кооперироваться. Однако, когда многопоточные программы не выполняются последовательно, понять их трудно. Инженерам не так-то просто идентифицировать баги и проблемы производительности в таких программах, как это делается в однопоточных программах с одной задачей.В Python вариантов конкурентности много. Самый распространённый, вероятно, – многопоточность, которой добиваются с помощью модуля threading и несколько процессов с помощью модулей myltiprocessing и subprocess, а также недавно появившийся способ – async из модуля asyncio. До появления VizTracer в инструментах, использующих эти техники в целях анализа программ, был пробел.VizTracer – инструмент отслеживания и визуализации написанных на Python программ, который помогает логировать, отлаживать и профилировать код. Хотя он хорошо работает в однопоточных программах с одной задачей, польза от него в смысле конкурентных программ делает инструмент уникальным.Попробуем с простой задачейОпределим, являются ли числа в массиве простыми, и вернём массив логических значений. Вот простое решение: def is_prime(n):
for i in range(2, n): if n % i == 0: return False return True def get_prime_arr(arr): return [is_prime(elem) for elem in arr] if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for _ in range(6000)] get_prime_arr(num_arr) viz_tracer my_program.py
Отчёт стека вызовов показывает, что выполнение кода заняло 140 мс, а большую часть времени заняло выполнение get_prime_arr. Здесь на каждом элементе массива выполняется функция is_prime. Это ожидаемо и не интересно, если VizTracer вам знаком.Теперь попробуем многопоточную программуСделаем то же самое в программе с несколькими потоками: if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for i in range(2000)] thread1 = Thread(target=get_prime_arr, args=(num_arr,)) thread2 = Thread(target=get_prime_arr, args=(num_arr,)) thread3 = Thread(target=get_prime_arr, args=(num_arr,)) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join() Если вы знакомы с Python Global Lock (GIL), то можете ожидать, что программа не станет быстрее: из-за оверхеда она выполняется немного дольше 140 мс, однако можно наблюдать конкурентность множества потоков: Когда работал один поток (и много раз выполнял функции is_prime), другой поток был заморожен (одна функция is_prime). Позже они поменялись. Это произошло из-за GIL, и причина в том, что в Python нет настоящей многопоточности. Возможна конкурентность, но не параллелизм.Попробуем поработать с multiprocessingЧтобы достичь параллелизма, воспользуемся библиотекой multiprocessing. Вот новая версия кода с применением этой библиотеки: if __name__ == "__main__":
num_arr = [random.randint(100, 10000) for _ in range(2000)] p1 = Process(target=get_prime_arr, args=(num_arr,)) p2 = Process(target=get_prime_arr, args=(num_arr,)) p3 = Process(target=get_prime_arr, args=(num_arr,)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() viztracer --log_multiprocess my_program.py
Вся программа занимает чуть больше 50 мс, задача завершается менее чем за те же 50 мс, то есть программа ускорилась приблизительно втрое. Чтобы сравнить производительность, напишем версию в несколько процессов: Без GIL множество процессов достигают параллелизма, то есть множество функций is_prime выполняются параллельно.Однако многопоточность в Python не бесполезна. Например, для вычислительно-интенсивных программ и программ с интенсивным вводом-выводом, при помощи sleep можно имитировать задержку ввода-вывода: def io_task():
time.sleep(0.01) if __name__ == "__main__":
for _ in range(3): io_task() .Вся программа занимает 30 мс; ничего особенного. Теперь воспользуемся многопоточностью: if __name__ == "__main__":
thread1 = Thread(target=io_task) thread2 = Thread(target=io_task) thread3 = Thread(target=io_task) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join() Выполнение занимает 10 мс: ясно, что все потоки работали одновременно и повысили производительность.Теперь поработаем с asyncioВ Python попробовали ввести интересную функциональность – асинхронное программирование. Нашу задачу можно написать асинхронно: import asyncio
async def io_task(): await asyncio.sleep(0.01) async def main(): t1 = asyncio.create_task(io_task()) t2 = asyncio.create_task(io_task()) t3 = asyncio.create_task(io_task()) await t1 await t2 await t3 if __name__ == "__main__": asyncio.run(main()) Всё те же 10 мс, но большинство отображаемых функций – нижележащая структура, которая, вероятно, не интересует пользователей. Чтобы решить эту проблему, можно использовать --log_async – флаг разделит задачу на части: viztracer --log_async my_program.py
Теперь задачи пользователя намного яснее. Большую часть времени выполняемых задач нет: единственное, что делает программа, – спит. Вот интересная часть: На временной шкале показывается, когда задачи создавались и выполнялись. Task-1 была сопрограммой mail(), которая создаёт другие задачи. Задачи 2, 3 и 4 выполняли io_task и sleep, а потом ждали пробуждения. Как показывает график, задачи не перекрывают друг друга, поскольку программа однопоточная, и VizTracer визуализировал её так, чтобы она была понятной. Чтобы сделать код интереснее, добавим вызов time.sleep, чтобы заблокировать асинхронный цикл: async def io_task():
time.sleep(0.01) await asyncio.sleep(0.01) Программа заняла намного больше времени (40 мс) и задачи заняли свои места в асинхронном планировщике. Это поведение очень полезно для диагностики проблем поведения и производительности в асинхронных программах.Смотрите на происходящее с помощью VizTracerПри помощи VizTracer вы видите, что происходит с программой, на временной шкале, а не читаете жалобы из логов. Это помогает лучше понимать вашу конкурентную программу.Исходный код VizTracer открыт под лицензией Apache 2.0, поддерживаются все операционные системы – Linux , MacOS, Windows. Вы можете узнать больше о его функциях и увидеть исходный код в репозитории VizTracer на Github. А освоить разработку на Python и стать Fullstack-разработчиком — на нашем специализированном курсе. Узнайте, как прокачаться в других специальностях или освоить их с нуля: Другие профессии и курсыПРОФЕССИИ
=========== Источник: habr.com =========== =========== Автор оригинала: Tian Gao ===========Похожие новости:
Блог компании SkillFactory ), #_open_source, #_python, #_parallelnoe_programmirovanie ( Параллельное программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:27
Часовой пояс: UTC + 5