LINUX.ORG.RU

Тредпул и таски, таски, таски

 , ,


0

3

Все никак не додумаю правильную архитектуру отвечающую целям.

База:

Приложение будет выполнять различные по типу таски.

Каждый таск перед его запуском будет отправлен в тредпул и в итоге выполнен в каком-то треде.

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

На завершение таска можно подписаться сигналом/каллбеком.

С выше описаным у меня проблем и непоняток нет. Едем дальше.

Цели:

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

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

Львиная доля одновременно существующих и выполняющихся тасков будут одного типа. Но они будут работать с разными данными.

В целом, это тоже не вызывает проблем в реализации.

Подводные камни:

Вижу два пути:

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

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

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

Атомики отпали сразу, т.к. состояние комплексное и поведение сильно зависит от типа таска.

Мьютексы/фьютексы/семафоры, да. Но, взяв самое медленное (мьютекс) возникает вопрос - не будут ли блокировки медленнее созданий-удалений?

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

Комплексно:

Свободные таски надо хранить в списке, по списку надо бежать, искать.

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

Чтобы узнать свободен ли таск нужно его сначала залочить. И так каждый в цикле.

Делать много списков где каждый хранит только конкретный тип (а типов дохрена, на крайняк группу близких типов?) тасков?

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

Да, надо бы тесты погонять. Не будут они сильно зависеть от проца, оси и прочего окружения?

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

Дай колбаски хлеб доесть, а?

pon4ik

★★★★★

Последнее исправление: deep-purple (всего исправлений: 1)

обусловлено необходимостью сегментировать задачи на максимально маленькие.

А задача совсем-совсем динамическая, или можно на старте порубить всё на кусочки?

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

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

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

несколько тасков можно предзаготовить

То есть некий шаблон всё-равно возможен. И эффективнее его будет сделать совсем-совсем постоянным?

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

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

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

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

Ну тогда и «резервирование» с ними тоже не очень то выйдет. В «теме» не предусмотрен вариант «постоянный шаблон»+«одноразовая мелочь».

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

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

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

у меня таки основной вопрос про динамическую мелочь - как с ней совладать минимально простаивая.

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

многоразовые и/или в одном экземпляре резервируются

Это не тоже самое. Одно дело разбить всё сразу на «2 группы», и другое - ворочить «сборную солянку».

anonymous
()

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

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

Ну и из описания не очень понятно что именно вам нужно, поэтому сложно посоветовать какой-то готовый инструмент. Тут может и уже упомянутый SObjectizer подойти, и cpp-taskflow (или TBB TaskGraph).

eao197 ★★★★★
()

А что, внутри самого таска или алгоритма его работы больше никаких аллокаций нету, вот только сама адллокация таска осталась? Просто за наоптимизируешь и потом поверх этого будешь строки клеить 50 раз внутри таска. Там вообще объектов динамической длины нету, векторов, строк?

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

сильно мелких задач, конечно, постараюсь не делать.

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

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

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

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от vertexua

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

deep-purple ★★★★★
() автор топика

То есть ты хочешь некий таск-пул запилить? Если он будет не динамическим, или даже динамическим но с лимитом количества тасков, то это попахивает дедлоками:

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

Не выделывайся и не усложняй. Если запилишь нормальный интерфейс для порождения тасков, то потом сможешь упороться и доделать.

Но это я так мимо проходил, на авторитетность в плюсах ни разу не претендую.

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

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

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от eao197

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

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

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

У тебя в пуле ограничение, допустим в 4 таска, и запущено 4, каждому нужно запустить по сабтаску и тут oh shi… они будут вечно ждать пока в пуле освободится таск.

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

10к в сек думаю потолок, но машинка у меня тестовая не айс, надо чтоб на ней пусть не летало но уверенно ехало.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от WitcherGeralt

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

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

до запуска в конкретном треде, даже одном, таски сидят в очереди и не квакают

Ну, если пул тасков сильно больше пула тредов, то пролема маловероятна, конечно.

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

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

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

я уже успел поговнокодить

Выложи ссылку на git. Облегчишь себе задачу и избавишь себя от мучений по разъяснению мелких деталей (они важны!).

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

бро, это проблема - инета весь день нет, пишу с тлф.

да и даже если - там щас песец, мне страшно комит пуш делать. все раскурочил.

позадавай наводящие что-ли

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

позадавай наводящие что-ли

Почему ты не хочешь поделить на «постоянные таски» и «одноразовые субтаски»? Это капитально всё упростит.

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

На 10K/sec можно не париться на счет динамического создания тасков. Просто создавайте и удаляйте. Изобретать велосипеды нужно когда вам потребуется больше нескольких миллионов в секунду.

Если бы мне потребовалось делать что-то подобное на SObjectizer-е, то я рассматривал бы два варианта:

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

2. На CSP-ных каналах. Т.е. под каждый тип таска создается свой канал. И вручную создаются рабочие нити для каждого канала. Нить висит на чтении тасков из CSP-канала, вычитывает очередной таск и исполняет его, затем читает следующий и так пока канал не закроют.

10k сообщений в секунду — это вообще ни о чем.

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

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

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

и когда они понадобятся и в каком количестве - хз.

А лучше вариант ты и не получишь, лучший вариант возможен только на «предсказуемой» задаче.

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

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

1 и 2 варианты подразумевают нить на тип? у меня сотня типов. а реальных нитей в проце может быть пшик. оно того стоит?

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

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

короче это деревья - глянь TBB

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

1 и 2 варианты подразумевают нить на тип?

Нет. Например, на агентах вы можете сделать так, что агенты A, B и C каждый работают на собственной нити, а агенты D, E, F и G на одной общей (или на одном thread-pool-е).

На CSP-каналах можно сделать так, чтобы одна нить читала из нескольких CSP-каналов. А можно сделать так, чтобы несколько нитей читало из одного канала.

Как захочется, так и можно сделать.

eao197 ★★★★★
()
Ответ на: комментарий от deep-purple

цепочка подвызовов может быть глубиной и до 10 сабтасков

Да хоть 100. Ты же ни один «уровень» «предсказать» не можешь. Каким же образом ты хочешь получить «выигрыш», если при каждом «чихе» делаешь полный цикл «проверок».

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

пусть не нить на тип, пусть сгребу типы в несколько групп - тогда неравномерно распределение нвгрузки на нити будет.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

вопрос - что быстрее, цикл проверок при поиске свободного таска или создании всегда на каждый чих нового?

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

что быстрее

Исходя из «предсказуемости» - второе. Оптимизация возможна только за счёт использования доп. инфы, магия не поможет.

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

хм... а вот это годно, надо пораскинуть мозгами. спасибо!

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

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

А в чем проблема пересоздать таск - в самой аллокации, или при создании еще какая-то работа делается? Если первое, то используй memory pool и не парься

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

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

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

список один общий сейчас где там что пересоздавать?

какие варианты еще?

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

резонно.

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

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

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

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

и без статистики можно

Можно конечно, только ты не получишь «выигрыша». Если «постоянных» мало - не «выигрыш», если «постоянных» много - не «выигрыш».

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

что быстрее

Тестить надо и на «больших количествах».

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

я не понял почему не получу выигрыша ни для так ни для эдак.

анекдот напомнил - мужик, ты туда не ходи - разденут. и туда не ходи - там тоже разденут. а что ж мне делать? тут раздевайся!

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

если каждый тип в своем списке то не схавают.

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

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

если каждый тип в своем списке то не схавают.

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

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