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

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

10.09.2013 11:18:54 Просмотров 27 Источник

Всем добрый день!

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

Опишу проблему подробнее. После перевода проекта под FreeBSD в многопоточный вариант, итоговая скорость работы не понравилась. Логика исходного проекта должна была остаться практически идентичной, и разнести данные по потокам так, чтобы, например, один поток работал только с одной структурой, и больше никуда не лез, не удалось. Соответственно, упор был сделан на "тонкую синхронизацию", - вышло множество блокировок и мьютексов, которые, теоретически, не должны захватываться кем-то надолго. Но теперь есть опасения, что наличие большого количества обращений к мьютексам выигрыш от использования многопоточки свело на нет. Поделитесь, пожалуйста, опытом, на что стоит обратить внимание, и есть ли какие-то еще возможности борьбы за скорость помимо полной переработки логики проекта?

UPDATE

Чтобы не было путаницы, опишу приближенную модель проекта. В рассматриваемой системе было 4 потока в расчете на 4 ядра:

  • 1-й - основной поток, обслуживает новые соединения, обрабатывает прерывания, и выполняет несрочную работу во время простоя;
  • 2-й - поток приема и обработки запросов от пользователей;
  • 3-й и 4-й - потоки выполняющие обработку разных частей трафика.

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

У вопроса есть решение - Посмотреть?

https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc#comment251653_251652
Хороший вопрос, я тожу жажду ответов) Плюсую.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc#comment251655_251652
@margosh А ваши опасения носят теоретический характер или все-таки у вас есть результаты профайлера + какой-нибудь штуки типа VS Concurrency Visualizer, но под FreeBSD? Если да, то можно на них глянуть?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc#comment251658_251652
у меня есть только результаты замера скорости трафика через модуль утилитой iperf, замеры эти проводились на виртуалке, и я им не всецело доверяю, но то, что скорость трафика через однопоточной модуль с той же логикой больше, меня напрягло, и я хочу узнать, какие у меня еще есть возможности для наращивания скорости. По поводу профайлера : к сожалению, Valgrind под FreeBSD, как я уже упоминала в некоторых моих темах, недописан, анализировать им работу многопоточной программы не выйдет, пока им можно только утечки искать.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc#comment266582_251652
@avp, все верно,во время этого тестирования через нее идут все пакеты, но я сейчас не тестирую каждое изменение - я перелопачиваю проект целиком, и пока не доделаю, результатов не узнаю. У Вас есть какие-то замечания к тестированию с помощью iperf?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc#comment266610_251652
@margosh, наверное нет. Кроме того, что я не понимаю, что он может делать кроме создания общей (и похоже максимальной) нагрузки (да, время или количество пакетов конфигурируется). А в чем суть программы? Сбор какой-то статистики из пакетов, проходящих через роутер? Или она вовсе не на роутере?

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

KoVadim

10.09.2013 11:42:20

Куча мютексом может очень хорошо затормозить программу. Ещё программу может затормозить промах кеша. К примеру, программа просто брала два массива и суммировала их в третий. Но массивы большие (сотни миллионов элементов). После распаралеливания 8 потоков работают с 8 массивами. И скорее всего 8*3 = 24 куска разных памяти не будут так хорошо влазить в кеш, будет постоянная подгрузка данных в кеш, и выгрузка (так как другим потокам также нужно). В этом случае уменьшение кол-ва потоков может дать существенный прирост.

Есть алгоритмы, которые просто так параллелить сложно. Например, расчет по рекуррентным формулам (когда последующий элемент зависит от предыдущего).

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

для начала классическим способом - профайлинг. Потом, когда подозрительные места найдены, поиском хороших алгоритмов. Например, иногда пузырьковая сортировка может быть значительно лучше quick sort - к примеру, известно, что данные почти всегда отсортированы и не больше 2-3 элементов стоит не на своих местах. quick sort в этом случае потратит много памяти, а по скорости вряд ли выиграет.

Что же делать?

  • уберите по максимуму мютексы и блокировки. Например, для разных счетчиков можно использовать atomic.
  • посмотрите на алгоритмы, возможно, применение sse даст прирост в 3-4 раза. Хотя иногда даже включение опции компилятора может все исправить.
  • пересмотр многопоточности. Возможно, OpenMP может сильно помочь. Он сильно может помочь, если нужно распараллеливать небольшие циклы, которые имеют "независимое тело".
  • отключение отладочного вывода. Как это не смешно:). У меня был случай, когда, убрав одну строку вывода в лог, код ускорился в десятки раз. Просто логгер был блокирующий с принудительным сбрасыванием в файл. Самое смешное - эта строка выводила время обработки блока кода, но по факту работала значительно дольше, чем сам код.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251667_251661
@KoVadim, спасибо. Правда у меня несколько другой разряд проекта - там нет псевдоодновременной работы потоков с идентичным функционалом над разными участками одного массива данных, к примеру. Есть потоки с разным функционалом, и кучка общих структур, обращение к которым из разных потоков как раз, на мой взгляд, все и тормозит. Количество потоков слишком большим я не развожу, это мы с Вами когда-то уже обсуждали. OpenMP смешивать с библиотекой pthread я пожалуй не рискну, а вот насчет атомиков и sse - нужно будет проверить
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251670_251661
Ну Вы же понимаете, что мне приходилось пальцем в небо тыкать? И то неплохо попал.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251687_251661
возможно, имеет смысл промоделировать такую систему как СМО
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251689_251661
@renegator, а можно подробнее?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251694_251661
Насколько я понял, у вас система не решает детерминированную задачу, а функционирует как система массового обслуживания (СМО). Грубо говоря СМО - это набор черных ящиков между которыми функционируют транзакты - заявки на обслуживание в ящиках. Большинство процессов в таком системе описываются как случайные величины - например поток входящих транзактов, время обслуживания в ящиках. В имитационных моделях обычно сразу видны узкие места таких систем
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251705_251661
ну не совсем, на данном этапе я как раз рассматриваю, возможно ли мою систему хотя бы частично привести к такому виду, чтобы потоки, как черные ящики, принимали и обрабатывали запросы, и не пытались залезать в пространство друг друга, однако пока не очень получается. а при помощи чего возможно провести моделирование подобных систем?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251708_251661
Я смотрел несколько средств, более всех известен язык GPSS
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251711_251661
@KoVadim, все правильно, только quick sort (не qsort() в ubuntu, который для массивов меньше 1/4 RAM (насколько помню) реализует mergesort) дополнительную память практически не использует.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251719_251661
я говорю не о конкретных реализациях. А так, да, производители компиляторов пытаются изобрести универсальную сортировку.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251727_251661
@renegator, спасибо, почитаю. Если у кого-нибудь есть еще мысли по поводу увеличения быстродействия, присоединяйтесь к диалогу пожалуйста. Чтобы не было путаницы, добавила более подробное описание системы в вопрос.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment251792_251661
Каждый объект данных, который используется потоками совместно, можно представить в виде канала обслуживания СМО с одним входом. Собственно к увеличению быстродействия осознание этого факта отношения не имеет
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251661#comment359915_251661
Пожалуй, в данном случае СМО должны решить проблему. Не говоря уже о том, что вы именно к такой модели и стремитесь.
avp

10.09.2013 02:13:53

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

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

Хотя, от VM тоже сильно зависит. Например, серверная VMware (за деньги) на сервере с Xeon-ами и бесплатный VirtualBox на Pentium (при сходных частотах) показывают существенно разные результаты.

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

Совершенно субъективно и навскидку: если работа займет меньше 1 миллисекунды, то создавать отдельный поток не стоит. Если меньше 0.01 миллисекунды, то даже в пуле предварительно запущенных потоков ее делать не надо. Помните, реальное перепланирование контекстов в ядре происходит (в отсутствии других событий) с частотой системного таймера (обычно 10 миллисекунд(!)).

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

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

https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251733_251710
@avp, скорость на оборудовании конкретно в настоящий момент не замерять по техническим причинам, позже естественно замеряю, и не 1 раз наверно. Добавила описание системы в вопрос, подразумевается, что каждый поток серьезно заргужен. О причинах перевода проекта в многопоточный вараинт так же упомянула. Поясните пожалуйста подробнее Ваше мнение насчет процессов : когда именно и почему Вы считаете их усместнее потоков?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251755_251710
@margosh, положа руку на сердце, скажу, что многопоточная программа напоминает карточный домик. Чуть не так что-то изменил ... и все падает. Только вот строить их занятие увлекательное. А по делу, если оборудование справляется или его можно разгрузить, выгнав лишних пользователей или можно купить более производительное железо, то для "боевых систем" лучше потоки не программировать. Только вот, это теперь модно и заказчики хотят многопоточности. Так что, если на Вас "давят" в этом плане, то киньте в пару потоков что-то тривиальное, лучше не требующее синхронизации.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251761_251710
ну за этот проект пока еще хотелось бы побороться, как то уж Вы совсем пессимистично все обрисовали...
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251776_251710
@margosh, это реальность, но вернемся к Вашей задаче. -- Я не совсем понял, эти 4 потока (видимо по числя ядер) стартуют в начале программы и потом как-то взаимодействуют для обработки данных, получаемых извне потоком 1? Если можно, поподробнее, как работает поток №2 с запросами пользователей? Насколько понимаю одновременно может обрабатываться несколько запросов. Кстати, это запросы вида вопрос-ответ (вроде RPC) или интерактивное взаимодействие в цикле? Потоки 3 и 4 как-то связаны по общим структурам данных?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251786_251710
1)да, все 4 потока стартуют практически одновременно; 2)нет, скорости запросов пользователей в данной системе не настолько интенсивны, поэтому обрабатываются последовательно, они действительно вида "вопрос-ответ", но подразумевают редактирование или чтение данных, которые используются так же в 3 и 4-м потоках. 3)да, есть структуры данных, которые используются во всех потоках, например те же списки : потоки 3 и 4 их проверяют, заполняют, в то время как поток №2 по запросу пользователей может читать эти списки, или редактировать(но вроде не так часто, как этим занимаются потоки 3 и 4).
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251814_251710
Да, представляю количество мьютексов и т.п. Попробуйте уменьшить их количество. Скажем, один мьютекс на все логически связанные структуры. Т.е. поток захватывает его, выполняет все работы, связанные с этими структурами, освобождает, захватывает второй мьютекс, работает, освобождает, ... берет следующий запрос.... Как я понимаю, смотреть время выполнения таких циклов бесполезно. Попробуйте просто их подсчитывать в локальных для каждого потока счетчиках и печатать, скажем раз в секунду. Все-таки что-то как-то мерять надо, невозможно говорить о производительности без конкретных цифр.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/251710#comment251821_251710
@avp, спасибо, подумаю над Вашим советом
Является ответом!
Михаил М

13.10.2013 08:32:25

Имеющихся в вопросе данных, конечно, очень мало, но что могу добавить:

  1. При решении вопроса о количестве потоков стоит идти не от задач, а от объёма работ. Т.е. я очень подозреваю, что сейчас потоки 1 и 2 в основном простаивают. Так что лучше, например, сделать ещё по одному потоку, аналогичному 3 и 4, а возможно и по 2-3. Таким образом, если будет идти много трафика, обрабатываемого потоком типа 3, всем 4-м физическим ядрам будет, чем заняться.

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

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

    Можно попробовать задать отдельный вопрос на эту тему

https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266509_261471
@Михаил М, спасибо, вобщем-то примерно к такому варианту взаимодействия и пришла, но проект пока еще в процессе переделки, посмотрим что из этого выйдет...
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266538_261471
@margosh, это хорошо, что Ваш проект живет и развивается. Если не сложно, то может напишите, как Вы меряете производительность? Вообще, какой поток (количество сообщений, их объем) поступает за секунду, а какой отправляется. Я понимаю, что могут быть пики нагрузки и "затишье". Навыерное более интересна "пиковая" ситуация, ну и м.б. в среднем.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266551_261471
@avp, просто гоняю трафик iperf-ом, и смотрю насколько скорость снизилась относительно пропускной способности канала.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266554_261471
@margosh, если честно, совершенно не понимаю, как таким способом можно оценить производительность своего приложения. Чем оно у Вас в самом деле занимается. Это часть роутера? Вы пропускаете через себя все пакеты?
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266562_261471
Т.е. я правильно понял, что на одном хосте вы запускаете iperf -s, на другом iperf -c ... , а в середине вносите изменения в свою программу и по [ 5] local 10.3.35.13 port 5001 connected with 10.3.19.42 port 44904 [ 5] 0.0-10.1 sec 112 MBytes 93.5 Mbits/sec подобной печати делаете выводы о целесообразности изменений? Если правильно понимаю, это как раз тестирование "пикового" режима.
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266563_261471
хм... вот этого не поняла "в середине вносите изменения в свою программу"... в середине - комп с моим сервером. да, это тестирование пикового режима, в прошлый раз его результат был не очень, все переписываю
https://ru.stackoverflow.com/questions/251652/%d0%92%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b1%d1%8b%d1%81%d1%82%d1%80%d0%be%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%8f-%d0%bc%d0%bd%d0%be%d0%b3%d0%be%d0%bf%d0%be%d1%82%d0%be%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/261471#comment266578_261471
Это наверное я Вас не понял. "в середине ..." это в предположении, что Ваша программа является частью роутера и все пакеты, генеримые iperf идут через нее. Тогда она будет где-то в середине цепочки приемников-передатчиков пакетов. Иначе я не понимаю, каким образом от Вашей программы зависит поток, который создает и измеряет iperf. (к сожалению последний коммент здесь. Если считаете дискуссию полезной, то куда-то ее надо переместить. Например, в комментарии прямо под вопросом).
dsnk

25.09.2015 03:19:47

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

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

PS: в Linux использую семафоры System V - можно выполнять операции над группой семафоров, например пробуждаться по освобождению обоих семафоров.

Закрыть X