【问题标题】:boost::shared_mutex slower than a coarse std::mutex on Linuxboost::shared_mutex 比 Linux 上的粗略 std::mutex 慢
【发布时间】:2016-05-18 14:58:42
【问题描述】:

我有一个std::unordered_map,它承受着来自多个线程的大量读取工作负载。我可以使用std::mutex 进行同步,但由于并发读取应该没问题,我想改用boost::shared_mutex。为了测试性能改进,我首先用一堆值预先填充了一个映射,然后让一堆线程运行read test

for (int i = 0; i < iters; ++i) map.count(random_uint(0, key_max));

我为我的coarse-lock implementation 运行此程序,其中countstd::lock_guard&lt;std::mutex&gt; 保护,而我的shared-lock implementationboost::shared_lock&lt;boost::shared_mutex&gt; 保护。

在我的带有 GCC 6.1.1 的 Arch Linux x86_64 系统上,boost::shared_lock 版本总是慢!在我朋友的带有 MSVC 2013 的 Windows 10 系统上,boost::shared_lock总是更快! 完整的、可编译的代码在 github 上:https://github.com/silverhammermba/sanity

编辑

这似乎是特定于平台的问题。往上看。如果其他人可以构建和运行此代码并报告他们是否看到正输出(shared_lock 更快)或负输出(当然互斥锁更快)以及您使用的平台,我将不胜感激。

【问题讨论】:

  • 不知道你为什么感到困惑。 shared_mutex 总是比普通互斥锁慢,RW-lock 在普通锁之上是额外的。作为练习,尝试自己实现 RW 锁。
  • 你为什么在线程中得到时间?你不应该只是在read_test 中获取两个循环之前的开始时间,然后在最后一个循环退出之后获取结束时间吗?
  • @NathanOliver 我想确保仅在所有线程运行后才记录开始时间,并且我不想在其中包括等待线程启动的时间。
  • @SergeyA 在这个测试中,我什至没有使用锁的 W 部分。我正在计时读取。如果这比等待轮到它的每个线程都慢,那么使用 RW 锁有什么意义呢?
  • @Max 但是你不知道所有线程什么时候结束。如果您仅从第一个线程开始和停止,您可能无法获得正确的结果。由于线程的创建和销毁应该是一个常量,因此在两个测试用例中都包含它不应该损害结果。

标签: c++ multithreading boost mutex boost-mutex


【解决方案1】:

原来boost::shared_mutex 在 Linux 上是 "suboptimal"

'pthread' 的 boost::shared_mutex 的当前(从 boost 1.59 开始)实现非常不理想,因为它使用重量级互斥锁来保护内部互斥锁状态...[当访问并发性很高时]共享互斥锁是有效排他性。

Hooray for boost 和我生命中的许多小时被它偷走了。

【讨论】:

    【解决方案2】:

    几点注意事项:

    1. 如果您的数据结构存在高争用,强烈建议使用具有无锁实现的相同数据结构

    2. Reader-Writer 锁通常在读取很常见时会带来性能提升,但写入很少。从哲学上讲,如果锁必须确定其他线程是否以读模式或写模式捕获了锁,它比简单地等待锁被释放要慢。因此,如果读取很常见而写入很少,则其他线程不会被阻塞。 如果写入很常见,不仅线程被阻塞,而且它们必须执行额外的逻辑来确定如何锁定什么。

    因此,总而言之,您的示例以不好的方式使用了锁。此外,如果性能符合您的要求,请使用无锁编程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 2013-08-27
      • 2014-02-02
      • 2013-12-05
      • 2015-04-18
      • 2019-11-07
      • 1970-01-01
      相关资源
      最近更新 更多