Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Общий LIFO стек для потоков


Автор: zss 6.8.2004, 08:03
Привет Всем !

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

Идея заключается в следующем: существует N потоков. Все эти потоки производят запись некой информации в специально выделенный буфер (а точнее свои TID). Любой поток, который
начинает выполнять код производит запись своего TID в буфер. Далее он что-то делает, а перед завершением работы удаляет свой TID. Пусть число записей = 256.

Первая идея, которая пришла в голову заключается в следующем:
1. Пришедший поток осуществляет поиск своего TID в цикле от
0 до 255.
2. Если TID существует, то общий код не выполняется.
3. Если его нет в списке, то он опять осуществляет поиск
от 0 до 255 и ищет свободную ячейку. А после этого выполняет код.
4. Когда поток отработал, он опять осуществляет поиск своего
TID от 0 до 255 и когда находит - очищает ячейку.

Данный алгаритм (я в том смысле, что именно до 255 и не прерывается) для максимальной загрузки. Тоесть уже 256 * 3 = 768 циклов !!!

А что если все организовать в виде общего стека LIFO для процессов. Тоесть существует некий указатель стека. В данном случае запись и удаление происходит по вершине стека, а поиск
только при поиске своего TID (хотя и здесь возможно его не нужно - пока не проверял. Естественно увеличение или уменьшение указателя стека осуществляется атомарно (с помощью Interlocked-функций). Производительность на 2 порядка возрастает.

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

Вопросы:
1. Будет ли это работать в многопоточном приложении.
2. Нужен ли цикл при поиске своего TID.
3. Допустим, что потоки с разными приоритетами будут корректно
прерывать друг друга и заносить значения в стек. А как быть с
потоками с одинаковым приоритетам (когда они конкурируют за даступ
к ресурсу и выбор зависит только то Операционной системы)
4. И еще ситуация: поток P1 произвел завись в стек, и в этот момент произошло переключение потока. Поток Р2 также произвел запись и сразу после этого истек его квант времени (или его просто убили). Далее поток Р1 получил управление и выполнил какие-то действия. После чего почистил стек по указателю. НО ! Он удалил не свой TID, а TID потока Р2 - а его TID остался в стеке. Как корректно реализацовать данный алгоритм.

Вобщем хочется услышать Ваши мнения

Спасибо

Автор: achmed 6.8.2004, 08:49
нужно использовать стандартные средства для синхронизации потоков (мьютексы, критические секции, функции типа join, waitfor, etc ..)

Автор: Олег М 6.8.2004, 10:22
Цитата
как оптимизировать собственный код,

Непонятно всё-таки, что ты пытаешься сделать.Что за код?

Цитата
А что если все организовать в виде общего стека LIFO для процессов

А с помощью обычного списка не пробовал? Или хэша, в смысле ассоциативные массивы. Стек-то зачем?

Цитата
1. Будет ли это работать в многопоточном приложении.

Вообще будет - смотря как реализуешь.

Цитата
2. Нужен ли цикл при поиске своего TID.

По моему лучше хранить для потока ссылку на его ТИД. Иначе, конечно нужен. Или используй хэш.

Цитата
3. Допустим, что потоки с разными приоритетами будут корректно
прерывать друг друга и заносить значения в стек. А как быть с
потоками с одинаковым приоритетам (когда они конкурируют за даступ
к ресурсу и выбор зависит только то Операционной системы)
4. И еще ситуация: поток P1 произвел завись в стек, и в этот момент произошло переключение потока. Поток Р2 также произвел запись и сразу после этого истек его квант времени (или его просто убили). Далее поток Р1 получил управление и выполнил какие-то действия. После чего почистил стек по указателю. НО ! Он удалил не свой TID, а TID потока Р2 - а его TID остался в стеке. Как корректно реализацовать данный алгоритм.

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

Автор: mr.DUDA 7.8.2004, 16:38
Если так уж не хочется делать синхронизацию - можно завести простейшую но удобную систему:
1) специально создаваемый поток - "контроллер потоков" работает с общей для всех потоков очередью команд
2) каждый поток имеет право добавлять данные в хвост очереди
3) пока очередь не пуста, контроллер потоков достаёт данные из головы очереди и выполняет действия для отдельной команды; если очередь пуста - контроллер ожидает, пока в ней появится хотя бы один элемент

Преимущества получаем такие:
1) добавление элемента в очередь - атомарная операция (в конечном итоге, она сводится к модификации одного указателя), поэтому это действие имеет право выполнять любой поток
2) анализировать и удалять элементы очереди имеет право только один поток - контроллер потоков

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

(С) mr.DUDA smile.gif

Автор: zss 8.8.2004, 11:30
Спасибо всем за советы.

Цитата
Если так уж не хочется делать синхронизацию 


Я не боюсь синхронизации - просто это замедляет работу данного участка, а мне нужна максимальная производительностьsmile.gif

Цитата
А с помощью обычного списка не пробовал? Или хэша, в смысле ассоциативные массивы. Стек-то зачем?


Стек - это просто как вариант решения (не обязательно он нужен smile.gif)

Я никогда не пробовал использовать хэш и т.п. Можно немного информации об этом или ссылоску

Спасибо

Автор: Олег М 9.8.2004, 07:49
Цитата(zss @ 8.8.2004, 14:30)
Я никогда не пробовал использовать хэш и т.п. Можно немного информации об этом или ссылоску

Посмотри классы map и hash_map в STL

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)