многопоточная медленная обработка c ++

У меня несколько потоков-потребителей и один поток-производитель. Поток-производитель записывает данные в карту, принадлежащую определенному потоку-потребителю, и отправляет сигнал потоку-потребителю. Я использую мьютексы вокруг карты, когда вставляю и стираю данные. однако такой подход выглядит неэффективным с точки зрения быстродействия. Можете ли вы предложить другой подход вместо map, который требует блокировок и разблокировок мьютексов, и я думаю, что мьютекс замедляет передачу.


person Avb Avb    schedule 27.09.2013    source источник


Ответы (2)


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

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


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

Производитель не должен беспокоиться о том, какую структуру данных использует потребитель - это деталь реализации потребителя. Имейте в виду, что для вставки значения в карту требуется выделение памяти (если вы не используете настраиваемый распределитель), а внутреннее выделение памяти также требует блокировок для защиты состояния кучи. Конечным результатом является то, что блокировка мьютекса вокруг map::insert операции может фактически заблокировать его слишком долго.

Более простой и эффективный вариант - иметь атомарную очередь между производителем и потребителем (например, pipe, TBB concurrent_bounded_queue, который предварительно выделяет свое хранилище, чтобы операции push / pop выполнялись действительно быстро). Поскольку ваш продюсер напрямую связывается с каждым потребителем, эта очередь является одним-писателем-одним-читателем, и ее можно реализовать как очередь без ожидания (или кольцевой буфер a-la C ++ disruptor).

person Maxim Egorushkin    schedule 27.09.2013
comment
Вы можете предложить какой-нибудь пример реализации этих очередей? Они стандартные в STL или где-то еще? Вы имеете в виду std :: atomic? - person Avb Avb; 27.09.2013
comment
@AvbAvb Я добавил пару ссылок. - person Maxim Egorushkin; 27.09.2013

Андрей Александреску правильно указал, что вам следует измерить свой код (https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920), и это тот же совет, который я дал бы вам: ваш код и посмотрите, какие различия в производительности вы получаете между базовым тестом и однопоточным тестом:

  1. Время, необходимое для вставки данных с использованием одного потока для сопоставления с данными, перечисленными выше
  2. Время, необходимое для вставки данных с использованием одного потока для сопоставления с данными, перечисленными выше, и с использованием блокировок мьютексов

Если вы все еще ищете поточно-ориентированный контейнер, вы можете посмотреть на реализацию Intel с открытым исходным кодом поточно-безопасных контейнеров по адресу http://www.threadingbuildingblocks.org/docs/help/reference/containers_overview/concurrent_queue_cls.htm >.

Кроме того, в качестве предложения по реализации потребительского потока вы можете прочитать статью ActiveObject, которую Херб Саттер разместил на своем веб-сайте: http://grassutter.com/2010/07/12/effective-concurrency-prefer-using-active-objects-instead-of-naked-threads/

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

person AhiyaHiya    schedule 27.09.2013