LINUX.ORG.RU

Гринтреды в питоне

 ,


0

3

Что лучше из этого greenlet/eventlet/gevent использовать и в чём у них принципиальное отличие? Четыре года писал на го, а сейчас есть необходимость писать на питоне, а без нормальной многопоточности из коробки даже дико как-то. В первую очередь интересует простота использования пула воркеров с точки зрения человека, забывшего питон как страшный сон.

★★★★
Ответ на: комментарий от noname_user

кстати да, а в чем проблема юзать выше описанное ?

Проблема может быть в том что не все библиотеки имеют асинхронные аналоги. Мне к примеру необходимо часто подключаться к mssql которая не имеет (во всяком случае мне неизвестен) асинхронного адаптера

Andreezy ★★
()
Последнее исправление: Andreezy (всего исправлений: 1)
Ответ на: комментарий от Andreezy

вот вроде как нашел пул реквест чувака - https://github.com/encode/databases/pull/151/files

а так - да, чет ничего подобного не вижу, возможно просто стоит перестать использовать mssql? (это я в плане если ты это делаешь в своем проекте, а не на работе).

в противном случае можно же и самому накидать что то подобное с использованием уже существующих либ?

noname_user ★★★
()

Четыре года писал на го, а сейчас есть необходимость писать на питоне, а без нормальной многопоточности из коробки даже дико как-то.

Оставайтесь на связи, мы занимаемся ваашим вопросом. Есть где-то на 70-80% готовая к публичному релизу (читай «альфа») либа для работы с разделенной памятью, близкая по своему интерфейсу к нормальной работе с питоновыми объектами, включая безопасное параллельное выполнение с управлением целостностью общих данных. В этом месяце публичного релиза точно не будет, а там еще неизвестно, понравится ли комунити реализация, сколько понадобится времени на доработку, и насколько нужно будет дорабатывать нужные тебе либы под новую модель.

А так, в текущем виде, многопоточности в питоне нет в принципе, модуль «threading» чисто случайно имеет общий корень с «thread».

В первую очередь интересует простота использования пула воркеров с точки зрения человека, забывшего питон как страшный сон

Для этого обычно используют серваки очередей, вроде кролика и кафки, где воркерами будет отдельный процесс питона, как это и заведено с 1991 года.

byko3y ★★★★
()
Ответ на: комментарий от t184256

А так, в текущем виде, многопоточности в питоне нет в принципе

«в принципе» != «пока GIL не подымешь»

Это уже многопоточка вне питона. Так же ты можешь запустить SQL запрос из питона, и он будет исполняться сервером в нескольких потоках — значит ли здесь, что питон многопоточен?

byko3y ★★★★
()
Ответ на: комментарий от noname_user

возможно просто стоит перестать использовать mssql? (это я в плане если ты это делаешь в своем проекте, а не на работе).

Как будто есть люди, которые в своих личных проектах на MSSQL завязываются. Причём даже не под .NET, а на питоне.

i-rinat ★★★★★
()
Ответ на: комментарий от byko3y

Так же ты можешь запустить SQL запрос из питона, и он будет исполняться сервером в нескольких потоках — значит ли здесь, что питон многопоточен?

Нет. А вот если на время исполнения запроса подымается GIL (а он подымается, если биндинги писал адекват) и ты можешь в других тредах зарядить полтос других запросов или что другое мутить, то питон внезапно многопоточен.

Это уже многопоточка вне питона.

Зависит от того, кого спросить.

Если спросить вычислистов-числодробистов, то скажут «сам ты вне питона».

Если спросить бизнес-логиков, то скажут «да ты упоролся бизнес-логику на тредах параллелить».

t184256 ★★★★★
()

Можешь закрывать тему как решенную, все что написали выше реальное положение вещей для python, есть асинхронность ей и пользуйся. Не нравится? Выноси поточнось за пределы python, и пиши хоть на том же golang. Еще в принципе есть биндинги, но это и есть одна из форм поточности за пределами python.

anonymous
()

Лучше скажи, какую задачу ты решаешь на тредах?

простота использования пула воркеров

threading.Thread

Aswed ★★★★★
()
Ответ на: комментарий от t184256

А вот если на время исполнения запроса подымается GIL (а он подымается, если биндинги писал адекват) и ты можешь в других тредах зарядить полтос других запросов или что другое мутить, то питон внезапно многопоточен

Блин, как же вы меня достали отвечать по сути то же, только другими словами. У того в учебнике по ТАУ за девяностый год другими словами написано то же самое по сути, тот выучил формулы из методички по расчету ЖД КА и теперь каждую собаку меряет по ним, ЕПРСТ, у этого не виноваты обучавшие пилота, а виноваты обучавшие пилота, но он до последнего будет рассказывать, что его точка зрения отличается от моей. Может, мне просто нужно поменьше сидеть на лоре.

Многопото́чность (англ. Multithreading) — свойство платформы (например, операционной системы, виртуальной машины и т. д.) или приложения, состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся «параллельно», то есть без предписанного порядка во времени

Поскольку потоки выстраиваются в очередь по GIL, то они не могут выполняться одновременно во времени в рамках питона — это кооперативная многозадачность, а вне питона может происходить что угодно.

https://ru.wikipedia.org/wiki/Многозадачность#Совместная_или_кооперативная_мн...

byko3y ★★★★
()
Ответ на: комментарий от byko3y

А нефиг использовать предельно дурацкое определение «в рамках питона». Так вообще дофигища кода работает «за рамками», а авторы и не знают.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

А нефиг использовать предельно дурацкое определение «в рамках питона»

Есть интерпретатор, есть стандартная библиотека — это и есть питон. Дополнительные сишные бибилотеки, сервер БД, операционная система — всё это не является питоном. Когда ты пишешь через threading чтение/запись файла, то ты создаешь запрос ОС и отпускаешь GIL на время вызова функий ядра ОС. Ты отдаешь управление из питона, это уже даже не пользовательский режим — это режим ядра, котором ядерные менеджер ввода-вывода в несколько потоков выполняет работу с накопителями. Но каким-то образом ты называешь это многопоточностью в питоне.

К слову, одно из замечательных следствий такого устройства — это сегфолт при завершении процесса, когда ОС внезапно возвращает управление, а интерпретатора питона уже нету.

byko3y ★★★★
()
Ответ на: комментарий от dnb

Задачу держать 50к сетевых воркеров

«А как наша корова не сдохнгешь?». Это же порядка сотни гигабайт оперативы нужно под такое.

byko3y ★★★★
()
Ответ на: комментарий от Andreezy

И тут мы возвращаемся к использованию потоков

Но, код при этом остаётся в синтаксисе async/await. Кмк, в довольном количестве aio* обёрток внутри потоки.

vvn_black ★★★★★
()
Ответ на: комментарий от dnb

Поднимай свой сервер через uwsgi. Не надо эту задачу решать питоновскими тредами, тем более, что всякие крупные фреймворки вроде django или flask дружат с uwsgi.

Aswed ★★★★★
()
Ответ на: комментарий от Andreezy

aioodbc

Кстати, тоже не совсем «таблетка от всего». Тут я тему поднимал, года 3-4 назад, aiomysql в тот момент (а может и до сих пор) работал через «тормозной» PyMySQL - в 10 раз медленнее селекты были чем через mysqlclient.

Стоял выбор обернуть запросы в ThreadPoolExecutor или использовать aioodbc, так вот в какой-то момент odbc-драйвер от оракла начал сегфолтиться, на что их поддержка просто развела руками «мы не можем воспроизвести ошибку».

vvn_black ★★★★★
()
Ответ на: комментарий от Andreezy

А в чем проблема? 3.5 и выше это не такое непосильное требование.

Kazun3500
()
Ответ на: комментарий от dnb

Воркеры бывают разные, мне хватает 12 гигов. Вот почитай https://habr.com/ru/post/262045/

Ну я ш про питон. Воркер может быть такой, что ему нужен только буфер в пару килобайт и килобайт стэка. Такая штука уместится и в гигабайт, там проблема будет скорее в том, как будет тупить планировщик ядра, и то не каждый. А питону нужно все значения в импортированных модулях завернуть в контейнеры, и потом туда-сюда дергать счетчик ссылок у них при сборке мусора:

>>> import sys
>>> sys.getsizeof('a')
50
>>> import gc
>>> len(gc.get_objects())
4604
>>>

Это с чистого листа запущенная командная строка питона.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Есть интерпретатор, есть стандартная библиотека — это и есть питон. Дополнительные сишные бибилотеки

Как удобно ты сейчас проигнорировал многочисленные нативные вставки в стандартной библиотеке. Их куда отнесешь?

Ты отдаешь управление из питона, это уже даже не пользовательский режим — это режим ядра, котором ядерные менеджер ввода-вывода в несколько потоков выполняет работу с накопителями. Но каким-то образом ты называешь это многопоточностью в питоне.

Ох, как у тебя удобно пропущено все между отпусканием GIL и сисколлами.

Давай заново, только без вот этих вот гигантских пропусков, сразу вся твоя риторика скатится под откос.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Как удобно ты сейчас проигнорировал многочисленные нативные вставки в стандартной библиотеке. Их куда отнесешь?

Приведешь пример?

как у тебя удобно пропущено все между отпусканием GIL и сисколлами

Там почти ничего нету. Делается drop_gil, системный вызов, take_gil.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Приведешь пример?

hashlib. zlib. какой-нибудь парсинг xmlятины.

Там почти ничего нету. Делается drop_gil, системный вызов, take_gil.

нативные модули — они не только тонкие обертки над сисколлами, есть еще как минимум обертки над жирными нативными либами. да и без них дочерта задач, где сисколлы не при чем, а производительность нужна. хватает их и в стдлибе питона.

Все еще не пропало желание спорить с «Так вообще дофигища кода работает «за рамками», а авторы и не знают»? Предлагаю признать нативный код стдлибы «в рамках питона» и завершить уже эту странную беседу.

t184256 ★★★★★
()

Гринтреды в питоне

М-да.
Ныне и катях «фейлом» называют.

anonymous
()
Ответ на: комментарий от t184256

zlib

Отпускает GIL только на вызов delfate/inflate, даже изменение размера буфера происходит вне GIL. То есть, сколько бы потоков с zlib у тебя не было — им все равно придется брать единый GIL и работать с памятью буфера под ним, а это в том числе копирование памяти. Конечно, zlib_decompress дает возможность пользователю угадать размер выходного буфера или взять сильно больше чем нужно, чтобы в процессе не нужно было копировать буфер в новую область — тогда копирование будет происходить под GIL один раз в конце распаковывания при изменении размера буфера под фактический объем данных.

hashlib

Вот это уже интереснее. Если не считать того, что ей нужен сплошной bytes-like буфер на входе (как и zlib), то пример вполне себе тянет на исключение. Я бы заметил, что для малых буферов (HASHLIB_GIL_MINSIZE 2048) работа с хэшами производится под GIL, потому что стоимость взятия-отпускания GIL сравнима с переключением на другой поток, но меньше стоимости какого-нибудь добавления потока в планировщик путем системного вызова изменения состояния мутекса или eventfd, по которым поток-воркер делает poll/select (жонглирование с GIL дешевле, чем стоящий пул внешних потоков-воркеров, но дороже безостановочной асинхронной обработки пулом воркеров).

То есть, я готов согласиться на позицию «питон не умеет в многопоток, кроме haslib над большими буферами» — потому что подсчет хэшей с малыми буферами будет только под GIL, как я уже написал.

какой-нибудь парсинг xmlятины

Это какой? В стандартной либе только expat, но там нет намеков на потоки.

нативные модули — они не только тонкие обертки над сисколлами, есть еще как минимум обертки над жирными нативными либами. да и без них дочерта задач, где сисколлы не при чем, а производительность нужна. хватает их и в стдлибе питона

Тупо по количеству упоминаний отпускание GIL вокруг системного вызова — это самое распространенное применение. То есть, fcntl, ioctl, sysconf, mmap, select, poll, сигналы, open/close, fopen/fprintf/fwrite, ну и самые разные сетевые запросы.

byko3y ★★★★
()

Асинхронщина!=многопоточность. Это то что стоит выяснить почти всем отписавшимся в треде. А задание на 4 это понять что такое GIL

peregrine ★★★★★
()

По теме питон не умеет в многопоточность. Многопоток надо выносить во внешнюю либу и через биндинг её юзать.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

По теме питон не умеет в многопоточность. Многопоток надо выносить во внешнюю либу и через биндинг её юзать

Я иду дальше и пишу, что стандартная либа питона не умеет в многопоток. То, что там называется потоками — это кооперативная многозадачность a.k.a. асинхронщина, которая реализована через потоки и объекты синхронизации ОС, а потому дороже, чем то же самое, сделанное через единственный поток. Собсна, все развитие асинхронщины в питоне и идет к тому, чтобы явно засунуть кооперативную многозадачность в один поток.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Отпускает GIL только на вызов delfate/inflate, даже изменение размера буфера происходит вне GIL. То есть, сколько бы потоков с zlib у тебя не было — им все равно придется брать единый GIL

А cpu time там и сидит. Отпустил GIL, расжимай, другие потоки бизнес-логику крутят. Успех.

я готов согласиться на позицию «питон не умеет в многопоток, кроме haslib над большими буферами» — потому что подсчет хэшей с малыми буферами будет только под GIL, как я уже написал.

Ну хоть что-то. Пока мы в нативном числодробительном модуле, питон может в многопоток =)

какой-нибудь парсинг xmlятины

Это какой? В стандартной либе только expat, но там нет намеков на потоки.

Это я, честно сказать, от балды ляпнул, как пример стандартной задачи, которую разумно делать внешней нативной либой и не нужно дергать сисколлы.

Тупо по количеству упоминаний отпускание GIL вокруг системного вызова — это самое распространенное применение.

Кто б спорил, но надо ж не по количеству упоминаний в стдлибе, а по проведённому времени измерять.

t184256 ★★★★★
()
Ответ на: комментарий от anonymous

@dnb @vvn_black @foozzi эти точно отметились ну или пофлудить пришли, про остальных либо оффтопик, либо знают, либо не определены. Потому как первый коммент должен быть такой, что либо крестик (python) снимите, либо трусы (сишку) наденьте.

peregrine ★★★★★
()
Ответ на: комментарий от t184256

Ну хоть что-то. Пока мы в нативном числодробительном модуле, питон может в многопоток =)

Не может. Numpy может, а питон нет. Или давай реализацию numpy на питоне.

peregrine ★★★★★
()

Поютубте «Гринтреды в питоне».

anonymous
()
Ответ на: комментарий от peregrine

numpy может, а питон нет

ну опять двадцать пять. hashlib может, а питон нет. если вы и дальше будете определять питон как ту часть питона, которая не может в многопоток, то да, питон не будет мочь в многопоток, по построению.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

А cpu time там и сидит. Отпустил GIL, расжимай, другие потоки бизнес-логику крутят. Успех

Распаковка zlib имеет производительность примерно 300-500 Мб/с. Грубо говоря, 6-10 циклов на байт. Освобождение-взятие GIL при наличии трений будет весить где-то 5-7 тысяч циклов (два системных вызова, снятие и постановка в планировщих), из них где-то половина будет внутри GIL. Если наша задача вне GIL требует меньше циклов, чем само переключение, то нет никакого смысла выполнять задачу вне GIL, потому что вне GIL она будет выполняться медленнее. В случае hashlib лимит — 2 килобайта, при этом скорость подсчета хэша составляет примерно 50-500 Мб/с, то есть, не быстрее zlib. В случае самого быстрого алгоритма, MD5, это значит, что hashlib начинает синхронный подсчет где-то с 6 тысяч циклов.

Если я рискну обрабатывать в потоках, например, большое число маленьких пожатых HTTP пакетов, то я внезапно обнаружу, что обработка в одном потоке потребляет столько же времени главного потока. А теперь вопрос: зачем мы делаем многопоточное приложение, если оно не работает быстрее? Чтобы поставить галочку «многопотоки есть»?

Да, компрессия-распаковка больших блоков параллелится неплохо, но я напоминаю, что во-первых bzlib, zlib, lzma являются внешними библиотеками, опционально собираемые с питоном, а во-вторых объясни мне, чем такие вызовы будут отличаться от «os.spawnl(os.P_DETACH, 'gz тра-та-та')»? Подготавливать входные данные и обрабатывать выходные нужно в обоих вариантах. Тужились-пыжились, чтобы притянуть за уши видимость многопотока в питон, а зачем? Вот же тебе многопоток с os.spawnl, всё параллельно, GIL не захватывается созданным процессом.

byko3y ★★★★
()
Ответ на: комментарий от t184256

ну опять двадцать пять. hashlib может, а питон нет. если вы и дальше будете определять питон как ту часть питона, которая не может в многопоток, то да, питон не будет мочь в многопоток, по построению

hashlib — это весьма узкоспециализированные задачи, это ведь даже не сертификаты и не SSL.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ок, ты меня убедил, допустим в стдлибе хорошего примера нет. Вне, конечно, есть, как готовые, так и самодельные.

Ускорение числодробилок есть, ускорение syscall-heavy кода есть, питон в моем виденьи мира все ещё многопоточен. Но ускорение бизнес-логики на питоне делать на потоках глупо, да.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Ускорение числодробилок есть, ускорение syscall-heavy кода есть, питон в моем виденьи мира все ещё многопоточен

В этих штуках питон исполняет роль «дергалки функций», там питона не больше, чем баша или ассемблера. Что, есть мало языков, который могут в потоках дергать системные вызовы? В этом заслуга не языка, а ОС, которая параллелит выполнение системных вызовов. Ровно так же параллелизация некой специализированной задачи, вроде числодробления, — это заслуга конкретной библиотеки, написанной на Си, а не питона и не его стандартной библиотеки.

В стандартной же библиотеке питона нет никакого решения для многопоточности, потому что все имеющиеся слишком специализированные, они не нужны для 99% пользователей языка, а общие решения требуют серьезного взаимодействия с самим языком, наличия гибкости и компонуемости, а там внезапно всплывает огромное кол-во препятствий для любой параллелизации. Я уже привел пример с zlib, в которой затрагивалась эта проблема, а именно: на объекты питона нельзя ни дунуть ни плюнуть вне GIL, и это очень сильно вяжет руки. И я планирую в скором времени предоставить решение, которое позволило бы хоть как-то решить эту проблему в общей форме, то есть работать с объектами многопоточно вопреки GIL.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ну удачи, держи в курсе, было бы реально круто.

t184256 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.