C++ 并行读/写哈希映射的最快解决方案是什么?
我正在编写一个网络服务,它接收原始数据包,然后将其转换并放入队列中。还有两个工作线程从队列中获取转换后的数据包,并根据一些规则更新哈希映射。为了防止来自不同工作线程的哈希映射的并发更新,我必须使用互斥。不幸的是,使用互斥锁会对性能造成很大影响。我需要找个工作来解决这个问题 编辑: 转换后的数据包包含一个会话id,此会话id用作哈希映射键。在任何插入或更新之前,首先搜索会话id,如果没有找到会话id,则添加一个新条目,这正是我使用互斥锁的地方,否则,如果会话id已经存在,我只更新现有值,并且没有用于值更新的互斥锁。知道我使用boost::unordered_-map作为底层哈希映射可能会有所帮助 下面是我使用的逻辑的psudo代码:C++ 并行读/写哈希映射的最快解决方案是什么?,c++,multithreading,performance,hashmap,network-programming,C++,Multithreading,Performance,Hashmap,Network Programming,我正在编写一个网络服务,它接收原始数据包,然后将其转换并放入队列中。还有两个工作线程从队列中获取转换后的数据包,并根据一些规则更新哈希映射。为了防止来自不同工作线程的哈希映射的并发更新,我必须使用互斥。不幸的是,使用互斥锁会对性能造成很大影响。我需要找个工作来解决这个问题 编辑: 转换后的数据包包含一个会话id,此会话id用作哈希映射键。在任何插入或更新之前,首先搜索会话id,如果没有找到会话id,则添加一个新条目,这正是我使用互斥锁的地方,否则,如果会话id已经存在,我只更新现有值,并且没有用
if hash.find(session_id) then
hash.update(value)
else
mutex.lock()
hash.insert(value)
mutex.unlock()
end
你有什么建议
顺便说一下,这是我的工作环境和工具:
编译器:C++(gcc)
线程库:pthread
OS:Ubuntu14.04最快的解决方案是以每个线程使用自己的数据集的方式分割数据,这样就不需要任何锁定。也许您可以通过基于一些关键数据在线程之间分发消息来达到目的
第二个最佳解决方案是使用C++ 11原子或C库函数实现读写自旋锁,参见
读写自旋锁通常允许多个并行读访问,但只允许一个写访问(当然也会阻止所有读访问)
Linux中也有读写互斥锁,但我发现它比手工实现稍慢。最快的解决方案是以每个线程使用自己的数据集的方式分割数据,这样就不需要任何锁定。也许您可以通过基于一些关键数据在线程之间分发消息来达到目的
第二个最佳解决方案是使用C++ 11原子或C库函数实现读写自旋锁,参见
读写自旋锁通常允许多个并行读访问,但只允许一个写访问(当然也会阻止所有读访问)
Linux中也有读写互斥锁,但我发现它比手工实现慢一些。您研究过无锁数据结构吗?你可以参考安德烈·亚历山德雷斯库(Andrei Alexandrescu)和魔法师迈克尔(Maged Michael)的一篇有趣的论文。例如,可以在Github存储库中找到一些使用类似思想的实现 尽管Facebook和Intel在某种程度上使用了锁定,但它们也提供了高性能的并发哈希映射
当然,这些方法需要一些额外的阅读和集成工作,但是如果您确定当前的锁定策略是瓶颈,那么它可能是值得的。您研究过无锁数据结构吗?你可以参考安德烈·亚历山德雷斯库(Andrei Alexandrescu)和魔法师迈克尔(Maged Michael)的一篇有趣的论文。例如,可以在Github存储库中找到一些使用类似思想的实现 尽管Facebook和Intel在某种程度上使用了锁定,但它们也提供了高性能的并发哈希映射
当然,这些方法需要一些额外的阅读和集成工作,但是如果您确定当前的锁定策略是瓶颈,那么这可能是值得的。我认为您需要添加从hashmap读取的频率,您更新hashmap的频率以及您拥有的hashmap读取器的数量。@SergeiKurenkov我添加了一些详细信息:)我认为您在这里有一个错误:
否则,如果会话id已经存在,我只更新现有值,并且没有用于值更新的互斥锁
。添加新密钥可能会导致hashmap重新分配内存,同时在另一个线程中访问密钥肯定会导致错误。当其他线程插入内容时,您不能在互斥锁外搜索映射。顺便说一下,我没有看到读取/秒的确切数字,写入/秒以及更新答案中的读者数量。我认为您需要添加从hashmap中读取的频率,您更新hashmap的频率以及您拥有的hashmap读取器的数量。@SergeiKurenkov我添加了一些详细信息:)我认为您在这里有一个错误:否则,如果会话id已经存在,我只更新现有值,并且没有用于值更新的互斥锁
。添加新密钥可能会导致hashmap重新分配内存,同时在另一个线程中访问密钥肯定会导致错误。当其他线程插入内容时,您不能在互斥锁外搜索映射。顺便说一下,我没有看到读取/秒的确切数字,更新答案中的writes/second和读卡器数量。+1我喜欢将会话ID与线程关联以避免完全锁定的想法,但您需要一种机制来根据ID将读写传递给特定线程,没有ID的搜索也更困难。+1我喜欢将会话ID与线程关联以避免完全锁定的想法,但您需要一种机制来根据ID向特定线程传递读写操作,没有ID的搜索也更困难。