Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

Возможности для увеличения быстродействия многопоточных программ

Всем добрый день!
Назрел очередной вопрос для тех, кто занимается многопоточными программами: каким образом вы улучшаете показатели быстродействия программы, в случае, если она не оправдала возложенных на нее в этом плане ожиданий?
Опишу проблему подробнее. После перевода проекта под FreeBSD в многопоточный вариант, итоговая скорость работы не понравилась. Логика исходного проекта должна была остаться практически идентичной, и разнести данные по потокам так, чтобы, например, один поток работал только с одной структурой, и больше никуда не лез, не удалось. Соответственно, упор был сделан на "тонкую синхронизацию", - вышло множество блокировок и мьютексов, которые, теоретически, не должны захватываться кем-то надолго. Но теперь есть опасения, что наличие большого количества обращений к мьютексам выигрыш от использования многопоточки свело на нет. Поделитесь, пожалуйста, опытом, на что стоит обратить внимание, и есть ли какие-то еще возможности борьбы за скорость помимо полной переработки логики проекта?
UPDATE
Чтобы не было путаницы, опишу приближенную модель проекта. В рассматриваемой системе было 4 потока в расчете на 4 ядра:
1-й - основной поток, обслуживает новые соединения, обрабатывает прерывания, и выполняет несрочную работу во время простоя; 2-й - поток приема и обработки запросов от пользователей; 3-й и 4-й - потоки выполняющие обработку разных частей трафика.
Все потоки в недетерминированные относительно друг друга моменты времени периодически читают и записывают данные в различные структуры (порядка 10 штук, включают различные счетчики, массивы с индексами), а так же читают и редактируют 4 различных списка. Основной идеей многопоточного варианта программы было отделить пользователей от обработки трафика, чтобы в случае высокой загрузки они не ждали очень долго, а так же увеличить скорость обработки трафика.


Ответ

Имеющихся в вопросе данных, конечно, очень мало, но что могу добавить: При решении вопроса о количестве потоков стоит идти не от задач, а от объёма работ. Т.е. я очень подозреваю, что сейчас потоки 1 и 2 в основном простаивают. Так что лучше, например, сделать ещё по одному потоку, аналогичному 3 и 4, а возможно и по 2-3. Таким образом, если будет идти много трафика, обрабатываемого потоком типа 3, всем 4-м физическим ядрам будет, чем заняться. Учитывая, что при текущем разделении по типу работ, возникает большое количество взаимодействий, гораздо лучше сделать несколько однотипных потоков, которые будут выбирать задания из общей очереди и класть результаты в другую общую очередь. Естественно, остаётся задача выделения работы, которую можно выполнять с минимумом взаимодействий. Наверняка можно что-то найти, парсинг запроса какой-нибудь или тяжёлые расчёты. Есть ещё различные приёмы для уменьшения конфликтов по данным. Например, создание пула памяти отдельно для каждого потока, чтобы они не толкались при выделении памяти. Или, скажем, каждый поток может подсчитывать какую-то статистику (как раз счётчики) только по тому, что он обработал, а потом, изредка, эта информация может объединяться в главном потоке. Можно попробовать задать отдельный вопрос на эту тему

Комментариев нет:

Отправить комментарий