Как проще всего избежать ограничений GIL? | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Python Developer. Professional
-3%
Разработчик на Spring Framework
-5%
iOS Developer. Professional
-8%
Golang Developer. Professional
-6%
Базы данных
-12%
Agile Project Manager
-5%
Android Developer. Professional
-11%
Microservice Architecture
-5%
C++ Developer. Professional
-5%
Highload Architect
-6%
JavaScript Developer. Basic
-8%
Backend-разработчик на PHP
-9%
Разработчик IoT
-13%
PostgreSQL
-8%
Алгоритмы и структуры данных Разработчик программных роботов (RPA) на базе UiPath и PIX Unity Game Developer. Basic Разработчик голосовых ассистентов и чат-ботов Vue.js разработчик VOIP инженер NoSQL Супер-практикум по использованию и настройке GIT Symfony Framework iOS Developer. Basic Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool"
Инфраструктура
DevOps практики и инструменты
-12%
Базы данных
-12%
Network engineer. Basic
-10%
Network engineer
-4%
Экcпресс-курс «ELK»
-10%
Инфраструктурная платформа на основе Kubernetes
-6%
Administrator Linux.Basic
-10%
Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes»
-30%
Дизайн сетей ЦОД
-13%
PostgreSQL
-8%
Разработчик программных роботов (RPA) на базе UiPath и PIX Reverse-Engineering. Professional Внедрение и работа в DevSecOps Administrator Linux. Advanced Infrastructure as a code in Ansible Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Экспресс-курс «IaC Ansible»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Как проще всего избежать ограничений GIL?

Python_Deep_8-5020-a10ed2.10_site.png

Многие из вас знают, что в Python есть GILGlobal Interpreter Lock, тот самый, который не даёт запускать несколько потоков и нагружать ядра процессора. Отчасти это так, но за GIL в Python скрывается очень много всего. И вот несколько фактов о нём:

GIL будет всегда. Но это не точно. — Захват GIL – одна из первых инструкций, которая выполняется в начале работы вашего кода. — Блокировка переключается каждые 100 инструкций байт-кода до версии 3.2. — Однако в Python до версии 3.2 у нас была возможность управлять этой цифрой. После – нет. — Всё потому, что в Python 3.2 и выше GIL был очень сильно переписан. Теперь блокировка переключается по времени. — Потоки соревнуются за захват GIL, у некоторых из них, например, тех, которые активно занимаются вводом\выводом, это получается чаще. — До версии 3.2 есть тонкости обработки сигналов при многопоточном коде – ваш код иногда может не получить сигнал от ОС. — Планированием выполнения потоков занимается ОС, а Python только говорит ей, как ему бы хотелось. — Вы можете обойти ограничения в своём коде при помощи multiprocessing. — Или написав своё Python C Extension.

Рассмотрим один из самых очевидных способов избежать ограничений GIL’а при выполнении CPU-intensive задач.

Модуль multiprocessing

Запускай по процессу на ядро и вперёд! К сожалению, очевидный способ не значит, что простой. Допустим, запускается процесс, который fork’ает дочерний процесс, но перед этим загружает в память какой-нибудь большой read-only кэш, необходимый этим процессам для функционирования.

Вот это класс! Казалось бы, за счёт copy-on-write (предполагаем Linux) оба процесса будут видеть один и тот же кэш, но дублировать его в памяти не придётся. В top (ну или ps) увидим, что у процессов RSS (Resident Set Size) меньше VMS (Virtual Memory Size). А если кто-то из них и решит туда записать, то ОС скопирует в его адресное пространство только нужные страницы.

Всё так, но есть нюансы

В Python управление памятью осуществляется с помощью reference counting. И даже простой цикл по списку, например, вызывает увеличение счётчика ссылок находящихся в нём объектов. То есть, скорее всего, наш большой кэш не останется надолго в общей памяти, а быстро скопируется в адресные пространства процессов.

Чтобы этого избежать нужно положить кэш в shared memory, то есть разделяемую память, которая является общей для обоих процессов. Multiprocessing даёт нам такую возможность, но выбор опций достаточно скудный: можно создать одно значение или массив. Для чего-то более сложного придётся использовать mmap, но программировать это будет ещё сложнее.

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться