Комментарии 27
"You have access to a restricted, sandboxed Python shell (mimicking an online service), and you need to gain broader access to the system. "
Без этой фразы я вообще не мог понять о чем Ваша статья и какую проблему Вы решаете. Помог только Гугл.
Я не считаю, что ограничение доступа к информации является лучшем решением.
Ну и третье, пользователи RM не получают за это никакой материальной выгоды, так что моя публикация не наносит никому какого-либо вреда.
Как и где он ограничивает? За 17 лет программирования на Python он меня ни разу не ограничил, и от других не слышал такого тоже.
Ну значит за 17 лет у вас ни разу не было потребности использовать больше 1 ядра эффективно в программе на Python-е.
Пример из моей недавней практики:
python скрипт, который раз в день обходит каталог с архивами с логами от нескольких серверов, парсит их и генерирует некоторые отчеты. Сам процесс анализа данных занимает от силы 30 секунд, но вот загрузка логов — около 10 минут (это бинарные логи в некотором своем формате, дополнительно сжатые gzip-ом, в разжатом виде около 5-6Gb логов на сервер). По скольку все сервера имеют однотипные логи, их более чем хочется загрузить параллельно и потом просто смержить результат, тем более что выполняется все на машине с 18 ядами (Xeon). Но не тут то было, из за global interpreter lock-а, из N python потоков всегда реально выполняется только один, остальные ждут возможности захватить GIL. Так что итоговая производительность загрузки при многопоточном подходе получается не в N раз быстрее, а раза вы полтора медленнее.
Если подытожить — то cpython реализация не позволяет эффективно использовать несколько потоков, вообще никак.
Если честно, я очень скептически отношусь к передаче большого количества DataFrame-ов, каждый порядка 500Мб в памяти, через pipe-а из дочерних процессов. Но попробую.
А зачем датафреймы-то передавать? Сразу используйте разделяемую память, а лучше анализируйте отдельно друг от друга в разных потоках / процессах.
Многие функции pandas
а однопоточны. Так что, собрав все в один большой датафрейм, вы многократно замедлите обработку.
Анализировать отдельно — это будет не так тривиально, т.к. код усыпан всякими groupby, делать их на отдельных маленьких DataFrame-ах а потом мержить вместе — только багов насажаешь.
А в разделяемую память класть — это нужно ведь будет ручками каждый отдельный столбец оформлять (а их там штук 50), а потом обратно собирать в дата-фрейм, что бы можно было анализировать при помощи pandas.
P.S.а вообще я попробовал, решение "в лоб" через pool.map приводит к тому, что около 5% времени уходит на передачу данных меж процессами. Не так ужасно, я думал будет хуже.
В любом случае — отсутствие нормальных потоков — это ограничивающий фактор. Тот же numpy по этой причине изворачивается с созданием нативных потоков, для параллельной обработки.
А про ограничение (архитектурное, замечу) языка стоит знать. Треды в языке вроде как есть. Но никто не задумывается, что в единицу времени будет выполняться ровно один тред. Мне кажется, это слишком интересная особенность чтобы о ней молчать.
Не понимаю, за что qrck13 заминусовали.
Не понимаю, за что qrck13 заминусовали.
Думаю, что минусы в основном за:
интересной особенностью о которой я не догадывалсяи
нигде вообще не удиляют внимания
Но никто не задумывается, что в единицу времени будет выполняться ровно один тред.
Если вы для себя Питон только что открыли, то да, никто не задумывается и все молчат :) А вообще, про этот GIL уже столько статей написано, столько копей поломано, что фактически нет смысла обсуждать…
У меня на работе мы в команде используем python как вспомогательный скриптовый язык (в основном для анализа данных при отладке основных проектов), основная разработка на C++/C#. Т.е. никто не изучал python на таком глубоком уровне. Но стандартный «common sense» на основании опыта с другими языками (у некоторых из команды — больше 20 лет опыта) никак не наводит на мысль, что в каком-то из языков может быть засада с такой базовой и основопологающей вещью как потоки. Когда я об этом «открытии» рассказал коллегам — сюрприз был у всех.
PS: Ему не multiprocessing нужен, раз bottleneck в загрузке, а не парсинге.
Во-первых, для парсинга логов отлично подойдет multiprocessing
, который распараллелит задачу на несколько процессоров.
Во-вторых, ввод-вывод хорошо ускоряется с помощью async / await
.
В-третьих, GIL при необходимости можно легко разблокировать с помощью cython
или numba
.
GIL при необходимости можно легко разблокировать с помощью cython
Но это уже будет не совсем python, хоть и запускаться процесс будет из python.
По тому же принципу можно просто через system запускать другие процессы (скрипты на python) в бекграунде и говорить, что GIL совершенно ничем никому не мешает :)
Лучше бы статью про root-me небольшую написали, за наводку на сайт спасибо.
Интересные особенности Python, о которых вы могли не догадываться