std::mutex 和 std::condition_variable 构造开销与堆分配

std::mutex and std::condition_variable construction overhead vs heap allocation

我有一个 task class 需要移动。我有大约 10-15 个任务包含在 task_storage 父 class 中。在 task::execute() 内部,我需要等待一个原子变量达到零:

void task::execute()
{
    for_subtasks([this]
        {
            thread_pool.post([this]
                {
                    this->do_work();

                    // Atomic counter.
                    --(this->_remaining_subtasks);
                });
        });

    // wait for `_remaining_subtasks == 0`
}

我想到了三种替代方法来等待 _remaining_subtasks == 0,同时保持 task 可移动:

  1. 使用 while(...){ sleep(1); } 忙等待循环。

  2. 在函数内部构造并使用一个 std::mutex 和一个 std::condition_variable

    void task::execute()
    {
        std::mutex m;
        std::condition_variable cv;
    
        for_subtasks(/* ... */);
    
        std::unique_lock<std::mutex> l(m);
        cv.wait(l, [this]{ return this->_remaining_subtasks == 0; });
    }
    
  3. task 中存储一个 std::unique_ptr<std::mutex> 和一个 std::unique_ptr<std::condition_variable> 作为字段。这将允许 task 可移动,但也会引入间接访问同步原语。

    void task::execute()
    {
        for_subtasks(/* ... */);
    
        std::unique_lock<std::mutex> l(*this->_m);
        this->_cv.wait(l, [this]{ return this->_remaining_subtasks == 0; });
    }
    

我不打算使用忙等待。我尝试分析 2 和 3 之间最快的解决方案,但无法获得任何有意义的结果。

std::mutexstd::condition_variable 的构造开销显着吗? 或者堆 allocations/accesses 会更慢吗?

Is the construction overhead for std::mutex and std::condition_variable significant? Or would the heap allocations/accesses be slower?

在这两种情况下都必须调用构造函数。不同之处在于分配内存的位置:静态存储、堆栈或堆。堆分配是最慢的。

在 Linux 和 POSIX 兼容系统上,std::mutexstd::condition_variable 是 POSIX pthread_mutex_t 和 [=13= 的精简包装器] 结构。初始化这些结构涉及设置基本类型的成员变量并且没有调用。换句话说,建造成本低。