2016-02-22 5 views
0

У меня есть функция pushMessage().Эффективность параллелизма в C++

void pushMessage(const char* msg, const int len) 
{ 
    for (int i=0;i<len;++i) 
     queue.push(*(msg+i)) 
} 

Очередь в вопросе является tbb::concurrent_bounded_queue<char> и имеет очень большой размер (предположим, бесконечное).

Эта функция вызывается двумя потоками. Один поток вызывает функцию постоянно, другой раз в то время.

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

P.S. - У меня есть доступ к библиотекам Boost и TBB.

EDIT: Очередь имеет тип char, поскольку она используется для отправки сообщений побайтно, для скорости. В предыдущей реализации было отправлено все сообщения за раз.

+0

Является ли это проблемой писателя-писателя или проблемой писателя-писателя? – DumbCoder

+0

Писатель-писатель. Оба потока записываются в очередь. –

+0

Что значит «для скорости» ??? В этой реализации это будет ** медленнее **. – SergeyA

ответ

3

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

Я, однако, сомневаюсь в мудрости текущего дизайна. Почему у вас очередь символов, когда семантика - это все сообщение? Не было бы лучше иметь целое сообщение как отдельный элемент очереди?

0

Одним из возможных решений могут быть использует boost::lockfree::queue<std::string>

Вы можете нажать и поп все сообщений без дополнительной синхронизации.

Если, как вы говорите, вы должны использовать байты, вы можете попробовать boost::lockfree::spsc_queue<char>. Там у вас есть члены

size_t write_available(size_t max_size) const 
size_type push(T const * t, size_type size) 

так вместе с взаимной блокировкой, вы можете написать что-то подобное в pushMessage методе

{ 
    boost::lock_guard<boost::mutex> guard(mutex_); 
    if(queue_.write_available(len)) 
     queue_.push(msg, len); 
} 
0

Что наиболее эффективный способ гарантировать, что содержимое очереди сделать не иметь сочетание параллельных сообщений?

Это был мой опыт (но в основном pre-C++ 11), что любой семафор мьютекса является «легким», когда потоки «редко» сталкиваются. То, что я из этого делаю, заключается в том, что контекстный переключатель должен быть дорогостоящим действием. Если критический раздел «разблокирован», стоимость проверки мьютекса небольшая.

Как правило, я использую (и рекомендую) мьютекс, а затем проследую тесты, чтобы проверить, соответствует ли поведение.

Один может быть полезным сравнение

а) сколько раз может один поток ввести мьютекс охранял критическую секцию (т.е.без конкуренции)

против

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

+0

На моем ubuntu15.10, g ++ 5.2.1, не оптимизированном и старше Dell hw, a) std :: mutex lock() и unlock() занимает около 47 nano-секунд; b) переключатель потоков C++ - 11, принудительно использующий std :: mutex занимает около 12 000 наносекунд. –