LINUX.ORG.RU

пвседвопотоки это лиш логическая организация программы а реальные потоки - это заюзывание простаивающих ядер

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

Это понятно, но стоит ли вообще использовать псевдопотоки?
Например для опроса сокетов?
И да(вопрос не по теме), почему нельзя создавать Threadpool внутри greenlet'а или в потоке сгенерированном други threadpool'ом.

deterok ★★★★★
() автор топика

Это имеет потенциальное преимущество, т.е. если разработчик псевдопотоков вдруг сделал их настоящими потоками, то ты получаешь булочку бесплатно. Так например в эрланге было сделано. Изначально вм эрланга однопоточная была, и все псевдопотоки (эрланг-процессы, акторы) крутились на одном ядре независимо от ядерности процессора. А потом вм (не помню с какой версии) она стала многопоточной, и соответственно разработчики под эрланг получили булочку бесплатно в новой версии вм.

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

AFAIK, есть ограничение на количество потоков в системе. Поэтому на каждое соединение создавать поток получается не всегда, к тому же получается большой оверхед на их шедулинг и прочее. Поэтому можно использовать либо мультиплексирование, либо псевдопотоки. Второе как правило проще и интуитивно понятней.

roy ★★★★★
()

Переключать контекст для псевдопотоков сильно дешевле, чем для настоящих. Эффективно при работе с мультиплексированием ввода-вывода вместе с блокирующими операциями, когда переключение контекстов и шедулинг нужен, а параллельность нет.

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

Поэтому можно использовать либо мультиплексирование, либо псевдопотоки.

Это вещи ортогональные.

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

но стоит ли вообще использовать псевдопотоки?

Смотря какая модель многозадачности реализована для них. Если вытеснющая, как в эрланге, то точно стоит. Если кооперативная (на практике обычно на корутинах делают), то лучше не надо. gevent вроде второе.

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

Тогда 2 вопроса: Чем вытесняющая модель многозадачность лучше кооперативной? И чем лучше организовать первую модель на python?

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

Что будет, если клиент запросит сервер произвести нехилую вычислительную операцию, а в тот момент будут идти более просты запросы от других клиентов? Все остальные будут ждать завершение громоздкой задачи?

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

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

Никогда не пробовал, но stackless python - вроде как раз реализация первой модели.

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

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

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

Вытесняющая лучше тем, что шедулинг производится автоматически.

чем это тогда лучше обычных тредов? оверхед на шедулинг будет все равно.

насколько я понимаю смысл кооперативной многозадачности, в том, что процесс сам решает, когда переключить тред, это значит, что на таких задачах, как работа с io-bound задачами, где блокирует только i/o она будет лучше чем вытесняющая (приложение лучше знает, когда передать управление в нужный тред)

chicane
()
Ответ на: комментарий от dizza

насколько я знаю, кооперативная многозадачность и не была приспособлена для cpu-bound задач, для них обычные треды - в самый раз, т.к. им нужно равномерное распределение процессорного времени.

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

чем это тогда лучше обычных тредов? оверхед на шедулинг будет все равно.

Оверхед будет конечно по сравнению с кооперативной многозадачностью. Но он будет небольшой и профита от удобства программирования сильно больше. К примеру в эрланге можно создавать десятки тысяч тредов и все бодро живет.

приложение лучше знает, когда передать управление в нужный тред

Это так ровно до того момента пока знает :) Если нужно написать что-то простое - то да. Но есть опыт написания большого портала в неблокирующем стиле и он показал, что раком выходит все это ручное управление. В жизни оказалось все гораздо сложнее. IO-bound задача может быть одновременно еще и CPU-bound, вот так внезапно. То есть ты не расчитывал, но жизнь оказалась сложнее - появилось такое требование.

Но в целом все так: если задача маленькая и чисто io-bound, то кооперативная многозадачность работает отлично. Для крупных проектов я бы это не стал использовать, а взял бы с вытесняющей (эрланг к примеру). Это чуть хуже по перфомансу, чем с кооперативной (но все равно лучше чем нативный тред на каждый конекшен), но зато глобально и надежно :)

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

Все так, но в жизни все бывает сложнее.

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

Да, gevent относится ко 2 типу, почитал на форумах, как правильно реализовывать разрывы в задачах. Там предлагается использовать sleep(0). Это в порядке вещей? (на мой взгляд это выглядит, ну не знаю как сказать, не эстетично)

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

если задача одновременно и cpu-bound то нужно взять пул нативных тредов и сделать задачу io-bound к ожиданию ответа от этого пула.

у меня тестов нет, но я уверен, что производительность кооперативной и вытеснящей многозадачности будет различаться на io-bound задачах сильно, особенно, если там >10K соединений, большая часть из которых находятся в ожидании. Я не знаком с ерлангом, но чем это отличается от нативных тредов, кроме того, что все реализованно в user-space?

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

gevent - это всего лишь попытка сделать код асинхронных приложений не разделяя поток управления. А по сути это такой же механизм как и twisted к примеру.

chicane
()
Ответ на: комментарий от deterok

Отстой это конечно :) А еще есть места, где вы этот sleep(0) не вставите, наверняка. В сишных любах каких-то например. А еще говорят он легко ломатеся этот gevent, но тут я точно не скажу, ищите инфу в гугле.

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

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

chicane
()
Ответ на: комментарий от deterok

вообще то ЕМНИП, в gevent есть hub поток, на который можно переключиться используя api гринлетов, но sleep(0) делает по идее тоже самое но короче )

chicane
()
Ответ на: комментарий от dizza

А еще говорят он легко ломатеся этот gevent, но тут я точно не скажу, ищите инфу в гугле.

да он немного криво реализован из-за того что является лишь либой к стандартному питону и делает хитрые манипуляции со стеком. По идее правильно все сделано в stackless питоне

chicane
()
Ответ на: комментарий от dizza

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

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

Может как раз можно не отадавать управление, а запустить бинарь в некоторой песочнице-виртуалке, стеком которого будет рулить процесс питона.

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

не знаю не использовал, но не понимаю до конца, как это связано? pyev это вроде просто биндинг к libev. gevent и сам вроде libev использует. gevent нужен тогда, когда задача io-bound (сеть например). gevent работает поверх libev и гринлетов (http://pypi.python.org/pypi/greenlet)

внутри gevent создается отдельный гринлет (псевдо тред с кооперативной многозадачностью), называемый хабом. Этот хаб - это аналог петли событий в обычных асинхронных фреймворках. Потом gevent определяет свои реализации сокетов и функций для работы с ними. Они полностью аналогичные питоновским, и gevent может заменить стандартные ими при желании. Отличие этих функций от стандартных в том, что вся инфа об операциях хранится во внутренних структурах gevent и в тот, момент когда стандартные фунции блокируют, эти функции переключают управление на хаб. Хаб в дальнейшем решает какому гринлету передать управление на основе того, что происходит с сокетами (при появлении новых данных например).

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

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

Да нет, почему же. Стеком рулить будем мы и в user-space это дешево (тока по ядрам не скейлится, а нам это и не нужно)

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

Ну как бы переключение нативных тредов неминуемо влечет потребность работы с железом и ядром. А в юзер спейсе все сводится к копированию состояния куда-то и заменой его новым. Принципиально все тоже самое, просто быстрее.

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

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

т.е. в простейшем случае, допустим у нас есть 9 потоков + 1 приложение запущено в системе, и ядро переключается между ними 10 раз в секунду, то если мы уменьшим число приложений до 2 (в одном будет реализация наших тредов), то ядро будет чаще переключаться между ними, и будет переключаться все равно 10 раз.

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

это конечно слегка наивное и упрощенное описание, но смысл в том, что все сильно зависит от реализации системы и отсутствии сильной выгоды на первый взгляд

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

А что если сделать смешанную систему: Для каждого сокета сделать псевдопоток ожидающий нужное событие и реакцией на которое будет добавление задачи в очередь с приоритетами. Также необходимо добавить псевдопоток занимающийся изъятием из очереди задач и закидыванием их в ограниченный пул реальных потоков. Как вам? Насколько жизнеспособна данная система?

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

А чем это лучше чем просто io-цикл? Суть таже, но реализация сложнее.

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

если честно я не понял до конца, что вы хотите. Смешать псевдопотоки и реальные потоки? я именно это и предлагал - использовать gevent для io-bound задач, а реальные потоки там где ожидается cpu-bound задача. Ну т.е. с точки зрения кода, мы пишем все в привычном для нас блокирующем стиле используя gevent, но имея ввиду, что если нужно исполнить тяжелую задачу, то кидать их в пул нативных потоков и ожидать заврешния работы этой задачи опять таки в блокирующем стиле с помощью gevent.

Вообще, я посмотрел на stackless - оно имеет внутри шедулер, который реализует вытесняющую многозадачность, но так же умеет и коопреативною, если под stackless есть что то похожее на gevent, то я думаю это будет в любом случае лучше, особенно учитывая кривую реализацию самих гринлетов (особенно на 64 битных архитектурах). Ипользуя стеклес с чем то похожим на gevent по идее вообще не прийдется заботится о таких вещах - все что надо (ожидания i/o будет кооперативно), а все остальное вытесняюще.

chicane
()
Ответ на: комментарий от dizza

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

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

нам не нужно думать в тех местах, где _не_ работает кооперативная многозадачность.

fix

chicane
()
Ответ на: комментарий от deterok

А что подразумивается под «что то похожее на gevent»?

реализация стандартных функций ввода/выводы с использованием кооперативной многозадачности. stackless дает только возможность запускать тасклеты - это больше аналог гринлетов.

chicane
()
Ответ на: комментарий от deterok

А libev разве не подойдет? Или я неправильно понял как он работает?

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

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

иначе всем тасклетам отведется примерно одинаковое время, и много времени потратится на ожидание i/o, в то время как другие тасклеты уже могут обработать данные

chicane
()
Ответ на: комментарий от deterok

Это понятно, но стоит ли вообще использовать псевдопотоки?

Упрощает жизнь в 2 случаях:

- когда лень напрягать мозг самому

- когда надо отдать часть работы быдлу, не способному выйти за рамки синхронных функций

Ну еще отлаживать в принципе проще, если код очень мудрёный.

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

https://github.com/halayli/lthread

What's special about lthread is that it allows you to make blocking calls and expensive computations inside a coroutine, providing you with the advantages of coroutines and pthreads. See the http server example below.

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

так мы же делаем фактически тоже самое, что и ядро - в чем дешивизна?

Ядро переключает машинный код, который может делать всё что угодно. Эрланг переключает ограниченные чистые функции, которые выполняют непосредственно вычисления - тут достаточно производить переключения каждые n вызовов функций, всё остальное делается асинхронными сообщениями - они не могут поломать переключения между процессами или помешать вытеснить очередной процесс (потому что асинхронные), сами сообщения управляются отдельными (настоящими уже) тредами IO и time managers, которые производят уже непосредственно мультеплексирование. Понятно, что настоящие треды в которых работают эти managers и лёгкие потоки могут быть разнесены по ядрам и прибиты по affinity. То есть, и по размеру структур отводимых на таски и по сложности алгоритма планирования ядро (которое должно угодить всем) и VM языка с лёгкими процессами (которая расчитана на один язык со специфичными свойствами) сильно отличаются.

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