有条件地获取 std::mutex

Conditionally acquire an std::mutex

本文关键字:mutex std 获取 有条件      更新时间:2023-10-16

我有一个使用 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() 更快,但在实际应用程序中,我的其他线程花费大量时间等待锁定,因此整体吞吐量更差。

浏览文档,在这个答案中,这似乎是可能的:

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实际上是不安全的。 我不熟悉您问题的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

您可以使用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*/);
    }
}