【问题标题】:Why does std::async copy its const & arguments?为什么 std::async 复制它的 const & 参数?
【发布时间】:2013-02-13 10:17:14
【问题描述】:

我正在尝试使用 std::async 来加速程序。假设我有一个函数

T* f (const T& t1, const T& t2, const T& t3)

其中 T 是一种复制成本很高的类型。我有几个带有不同参数的独立 f 调用,我尝试将它们与 std::async 并行化,大致如下:(其中 m_futures 是正确类型的期货的 std::vector)。

for (...) {
   m_futures.push_back (
       std::async(
           std::launch::async,
           f,
           a,b,c));
}

我观察到上面的代码减慢了我的程序的执行速度。我用 gdb 逐步完成了它,当创建未来时,T 的复制构造函数被调用了 3 次。这是为什么?参数 a,b,c 是堆分配的,但编译器可能不知道吗?我可以以某种方式使其明确吗?

std::async 是否总是创建参数的副本,即使它们应该通过 const 引用传递?我能以某种方式避免这种情况吗?在我天真的想法中,应该只传递一个指向函数的不同调用的指针(无论如何它只能从内存中读取。)如果这很重要,我在 Linux 上使用 gcc-4.6.3。

【问题讨论】:

    标签: c++ gcc asynchronous c++11 std


    【解决方案1】:

    只存储引用是不安全的,因为没有什么可以保证不存在数据竞争(更深刻地说,只是对象的存在,正如@utapistim 在她遗憾地删除时所说的那样发布)。

    如果你真的想要一个参考而不是一个副本,并且愿意赌上你的生命,那么你可以简单地使用一个参考包装器:

    std::async(std::launch::async, f, std::cref(a), std::cref(b), std::cref(c))
    

    【讨论】:

    • 出于好奇,如果我更改接口并显式传递指针会怎样?这是否等同于使用引用包装器?
    • @Thomas:是的。引用包装器本质上是指针。不要在 C++ 中使用裸指针(私有类成员除外)。更喜欢参考包装器。
    • 好的,谢谢,我不知道引用包装。
    • @KerrekSB 好吧,最初可能更适合std::bind 和朋友,并适应(11 之前)缺乏完美转发来自动推断引用参数。
    • @ChristianRau,你说得对,它是为std::bind 发明的,但我看不出完美转发与它有什么关系,能够区分左值和右值并没有帮助调用包装器知道它应该通过值还是通过引用转发参数,只有调用者才能知道哪个适合给定调用。
    猜你喜欢
    • 2020-05-25
    • 2012-12-27
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 2019-08-22
    • 1970-01-01
    相关资源
    最近更新 更多