【问题标题】:How can std::lock_guard be faster than std::mutex::lock()?std::lock_guard 如何比 std::mutex::lock() 更快?
【发布时间】:2019-12-09 20:30:16
【问题描述】:

我在和一位同事争论 lock_guard,他提出 lock_guard 可能比 mutex::lock() / mutex::unlock() 慢,因为实例化和非实例化类 lock_guard 的成本。

然后我创建了这个简单的测试,令人惊讶的是,带有 lock_guard 的版本几乎比带有 mutex::lock() / mutex::unlock() 的版本快两倍

#include <iostream>
#include <mutex>
#include <chrono>

std::mutex m;
int g = 0;

void func1()
{
    m.lock();
    g++;
    m.unlock();
}

void func2()
{
    std::lock_guard<std::mutex> lock(m);
    g++;
}

int main()
{
    auto t = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000; i++)
    {
        func1();
    }

    std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;

    t = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000; i++)
    {
        func2();
    }

    std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;

    return 0;
}

我机器上的结果:

Take: 41 ms
Take: 22 ms

有人能解释一下为什么会这样吗?

【问题讨论】:

  • 你测量了多少次?
  • 请发布您的编译器标志...基准测试将取决于优化级别...
  • 专业提示:进行这样的测量时,请交换顺序以确保导致问题的不仅仅是冷数据/指令:coliru.stacked-crooked.com/a/81f75a1ab52cb1cc
  • 在进行这样的测量时另一件很有帮助的事情:将整个事情放在一个更大的循环中,这样您就可以运行整个测量集,例如,每次运行 20 次。通常后面的测量值才是真正有意义的,因为到那时缓存已经适应了它可能长期存在的任何行为。
  • 即使std::lock_guard 有点慢,除非你能证明它在性能方面很重要,否则速度提升不会使使用std::lock_guard(主要是RAII)的其他好处无效。如果g++ 是可以抛出的任何东西,或者任何可能在未来变得更复杂的东西,那么您几乎必须使用某种对象来拥有锁。

标签: c++ mutex


【解决方案1】:

发布版本对两个版本产生相同的结果。

DEBUG 构建显示 func2 的时间延长了约 33%;我在反汇编中看到func2 使用__security_cookie 并调用@_RTC_CheckStackVars@8 的区别。

你在计时 DEBUG 吗?

编辑: 此外,在查看 RELEASE 反汇编时,我注意到 mutex 方法保存在两个注册表中:

010F104E  mov         edi,dword ptr [__imp___Mtx_lock (010F3060h)]  
010F1054  xor         esi,esi  
010F1056  mov         ebx,dword ptr [__imp___Mtx_unlock (010F3054h)]  

并从func1func2 以相同的方式调用:

010F1067  call        edi  
....
010F107F  call        ebx  

【讨论】:

    猜你喜欢
    • 2017-03-28
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 2018-10-07
    • 1970-01-01
    相关资源
    最近更新 更多