2013-09-27 153 views
0

我有多个消费者线程和一个生产者线程。生产者线程将数据写入属于某个消费者线程的映射中,并向消费者线程发送信号。当我插入和擦除数据时,我在地图周围使用互斥锁。但是这种方法在速度性能方面看起来效率不高。你可以建议另一种方法,而不是地图,需要互斥锁和解锁,我认为互斥减慢传输。C++多线程缓慢处理

回答

2

但是这种方法在速度性能方面看起来效率不高。你可以建议另一种方法,而不是地图,需要互斥锁和解锁,我认为互斥减慢传输。

您应该使用分析器来确定瓶颈的位置。


生产者线程把数据写入到地图属于某个消费者线程并发送信号给消费者线程。

生产者不应该关心消费者使用什么样的数据结构 - 这是消费者的实现细节。请记住,将值插入映射需要内存分配(除非使用自定义分配器),并且内存分配内部也会锁定以保护堆状态。最终的结果是锁定一个互斥量大约在map::insert的操作可能会将其锁定的时间太长。

一个更简单和更高效的设计是在生产者和消费者之间有一个原子队列(例如pipe,TBB concurrent_bounded_queue,它预先分配它的存储以便推/拉操作非常快)。由于您的生产者直接与每个消费者进行通信,因此该队列是一个一个读写器的阅读器,并且可以实现为一个等待队列(或环形缓冲区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. 插入使用单线程与上面列出的数据映射,并使用互斥 锁数据 所需的时间映射 插入数据所需的时间

如果你还在寻找一个线程安全的容器,你可能想看看英特尔的开源实施线程安全的容器http://www.threadingbuildingblocks.org/docs/help/reference/containers_overview/concurrent_queue_cls.htm

而且,对于消费者线程执行的建议,您可能需要阅读的的activeObject文章认为香草萨特张贴在他的网站:http://herbsutter.com/2010/07/12/effective-concurrency-prefer-using-active-objects-instead-of-naked-threads/

如果你能提供一些更多的细节,比如为什么地图必须始终锁定,我们可能能够起草一个效果更好的机制。