2013-09-27 3 views
0

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

ответ

2

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

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


Производитель поток записывает данные в карту принадлежат к определенному потребительскому потоке и посылает сигнал на потребительский поток.

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

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

+0

Можете ли вы предложить пример реализации этих очередей? Являются ли они стандартными в STL или где-то еще? Вы имеете в виду std :: atomic? –

+0

@AvbAvb Я добавил пару ссылок. –

0

Andrei Alexandrescu отметил, что вы должны измерить свой код (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 что Herb Sutter разместил на своем сайте: http://herbsutter.com/2010/07/12/effective-concurrency-prefer-using-active-objects-instead-of-naked-threads/

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

Смежные вопросы