LINUX.ORG.RU

треды


0

0

Есть пул тредов все они работают ассинхронно получая данные от одного треда (INPUT) и отдавая данные другому (OUTPUT). Вопрос: как вы считаете лучше организовать I/O ? Приходят в голову два варианта:

1) INPUT перебирает в цикле все треды пока не найдет свободный, дает ему данные и активизирует его. Так же в цикле опрашивает все треды OUTPUT, находит отработавший, забирает данные и деактивизирует его.

2) Тред отработав блокирует очередь "готовых отдать данные тредов", добавлет туда себя, разюлокирует очередь и засыпает. OUTPUT блокирует ту же очередь, достает информацию, разблокирует очередь, блокирует очередь "готовых принять данные тредов", добавляет туда информацию об этом треде и разблокирует очередь. INPUT блокирует эту очередь, достает от туда информацию о свободном треде, разблокирует очередь, передает данные треду и активизирует его.

Что лучше ? Во-втором случае информация о конкретном свободном треде но сплошные блокировки, в первом случае отсутствие блокировок но тупой перебор все тредов...

Что будет быстрее работать ???

anonymous

1-й вариант условно годится (впрочем, см. дальше) лишь в одном случае -- если у тебя мастер-тред ЗАВЕДОМО монополизирует один процессор. Так, кстати, обычно поступает MPICH...

Он меня ДОСТАЛ! Только для пузомерок, специально для этого написанных, годится. В любой реальной задаче ТАК ДЕЛАТЬ НЕЛЬЗЯ! (согласно моему опыту, конечно).

2-й вариант -- нормально, только всегда надо думать про оптимизацию блокировок. На этот счет есть несколько (квази-)математических теорий, кстати!

Die-Hard ★★★★★
()

Хм...а с пайпами не проще будет? INPUT открывает пайп на запись, куда пишет данные. Треды в очереди читают из этого пайпа, если данных нет - то они тупо висят на вызове read(). Если данные большого размера - то в пайп мона писать указатель на данные. Тред OUTPUT открывает пайп на чтение, в который пишут треды. Так же висит на вызове read() когда данных нету.

AFAIK, read() и write() на пайпе атомарны для данных, размер который не превышает 512 байт (точное значение в каком-то заголовочном файле)

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

> ...а с пайпами не проще будет?

Это ЧАСТНОСТИ, про которые речи вообще не было. Речь шло про общую страрегию синхронизации.

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

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

roy ★★★★★
()

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

anonymous
()

Возможно, я недопонял задачу, но ИМХО проще было бы через сокеты: INPUT хранит отдельно списки занятых и свободных тредов, при появлении данных извлекает из списка свободных тредов один и пихает туда чё-нибудь. Тред висит соответственно на poll/select когда не занят. OUTPUT юзает poll/select по всем тредам. Когда получит данное из треда, по сокету же передаёт в INPUT информацию чё такой-то тред уже освободился, из-за чего INPUT перенесёт ево из списка занятых в список свободных.

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

Я [другой anonymous] сделал бы следующий вывод: второй вариант - однозначно. Выбор механизма для организации очередей, который требовал бы поменьше блокировок, можно оставить на потом, а для начала стоит лишь сделать какую-нибудь правильную обертку вокруг мютексов и STLных очередей, которые кажутся удачной starting point.

Под Windows я бы смотрел в сторону Slists (они реализованы на Interlocked операциях), но их аналога, доступного под Linux, я, к сожалению, не знаю.

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

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

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

>но их аналога, доступного под Linux, я, к сожалению, не знаю.

Эти 10 строчек написать чтоли проблема.. поиск на comp.programming.threads

Как-то натыкался и на Си++ либу с кучей всевозможных lock-free/wait-free алгоритмов кроссплатформеную..

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

>Как-то натыкался и на Си++ либу с кучей всевозможных >lock-free/wait-free алгоритмов кроссплатформеную..

lock-free/wait-free ??? Интересно... Название не подскажите ?

anonymous
()

pipe вроде не идеальный вариант.

Правильно ли я понимаю что подобную read на pipe блокировку можно сделать на pthread_cond_wait в тредах и pthread_cond_signal в INPUT ? имхо так красивей и функциональней...

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

anonymous (*) (11.09.2006 9:50:33):

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

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

> Под Windows я бы смотрел в сторону Slists (они реализованы на Interlocked операциях), но их аналога, доступного под Linux, я, к сожалению, не знаю.

Только самодеятельность с привлечением assembler + compiler intrinsics -- в Це, к сожалению, такого нет... Впрочем, вожможно, есть уже готовое?

Кстати, как я понимяю, в Вындузе оно работает только на IA-32?

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

+1

В 90% нитки вредны (особенено в виде пула), и все ЗНАЧИТЕЛЬНО проще делается на процессах (и работает быстрее!) с синхронизацией пайпами.

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