【问题标题】:Conditionally acquire an std::mutex有条件地获取一个 std::mutex
【发布时间】:2017-03-29 02:34:28
【问题描述】:

我有一个使用 GPU 的多线程应用程序,它本质上是单线程的,而我使用的实际 API cv::gpu::FAST_GPU 在我尝试多线程使用它们时确实会崩溃,所以基本上我有:

static std::mutex s_FAST_GPU_mutex;

{
    std::lock_guard<std::mutex> guard(s_FAST_GPU_mutex);
    cv::gpu::FAST_GPU(/*params*/)(/*parameters*/);
}

现在,对代码进行基准测试显示我在隔离时 FAST_GPU() 比 CPU FAST() 快,但在实际应用中,我的其他线程花费大量时间等待锁定,因此整体吞吐量更差。

查看文档,at this answer 似乎这是可能的:

static std::mutex s_FAST_GPU_mutex;
static std::unique_lock<std::mutex> s_FAST_GPU_lock(s_FAST_GPU_mutex, std::defer_lock);

{
    // Create an unlocked guard
    std::lock_guard<decltype(s_FAST_GPU_lock)> guard(s_FAST_GPU_lock, std::defer_lock);
    if (s_FAST_GPU_lock.try_lock())
    {
        cv::gpu::FAST_GPU(/*params*/)(/*parameters*/);
    }
    else
    {
        cv::FAST(/*parameters*/);
    }
}

但是,这不会编译为 std::lock_guard 只接受 std::adopt_lock。我怎样才能正确地实现它?

【问题讨论】:

  • 我不确定你为什么使用静态unique_lock,因为通常你不希望2个线程访问同一个unique_lock。也就是说,我会删除 s_FAST_GPU_LOCK,然后使用std::try_to_lock,并使用owns_lock 测试它是否成功。
  • @DaveS 啊,我明白了 - mutex.try_lock() 然后是 lock_guard&lt;&gt;(std::adopt_lock)?请将此作为答案。

标签: c++ opencv c++11 mutex


【解决方案1】:

同时从多个线程访问unique_lock 实际上是不安全的。我不熟悉你问题的 opencv 部分,所以这个答案主要集中在互斥锁/锁的使用上。

static std::mutex s_FAST_GPU_mutex;
{
   // Create a unique lock, attempting to acquire
   std::unique_lock<std::mutex> guard(s_FAST_GPU_mutex, std::try_to_lock);
   if (guard.owns_lock())
   {
       cv::gpu::FAST_GPU(/*params*/)(/*parameters*/);
       guard.unlock(); // Or just let it go out of scope later
   }
   else
   {
       cv::FAST(/*parameters*/);
   }
}  

这会尝试获取锁,如果成功,使用FAST_GPU,然后释放锁。如果锁已经被获取,则进入第二个分支,调用FAST

【讨论】:

  • 这看起来不错,更接近简单案例的模式,所以应该比我的建议更容易理解。
  • 哦,原来是纯CPU版本比尝试上面的分工要快。它按照您描述的方式运行,因此是时候打破 GPU 分析器以查看是否有其他东西占用了 GPU。
  • 我不能肯定地说,但是只要 cpu 接触数据,拆分工作几乎肯定会强制 GPU 上的命令缓冲区停止,因为它必须重新上传该数据才能处理,这命令缓冲区停顿可能会导致 gpu 操作在锁内阻塞,具体取决于实现。
【解决方案2】:

你可以使用std::lock_guard,如果你采用互斥锁处于锁定状态,像这样:

{
    if (s_FAST_GPU_mutex.try_lock())
    {
        std::lock_guard<decltype(s_FAST_GPU_lock)> guard(s_FAST_GPU_mutex, std::adopt_lock);
        cv::gpu::FAST_GPU(/*params*/)(/*parameters*/);
    }
    else
    {
        cv::FAST(/*parameters*/);
    }
}

【讨论】:

    猜你喜欢
    • 2017-03-28
    • 1970-01-01
    • 2013-12-29
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多