【问题标题】:Execution policy problem with lambda expressionlambda 表达式的执行策略问题
【发布时间】:2018-09-10 14:02:01
【问题描述】:

我有这门课:

class EMX_Counter {
    private:
        std::vector<std::unique_ptr<WireBase>> WiresList;
    public:
        EMX_Counter(const std::vector<std::unique_ptr<WireBase>>& w) : WiresList(w) {}
        EMX_Counter(std::vector<std::unique_ptr<WireBase>>&& w) : WiresList(std::move(w)) {}
        std::future<std::vector<double>> getEmxEfficiency();
    };

WireBase 是一个抽象类(在这里它如何工作并不重要),我需要一个唯一的 ptr,因为我需要多态性。也就是说,getEmxEfficiency() 需要一些时间,因为该向量包含至少 28'000 / 30'000 个项目,并且对该方法的一次调用很慢。

我决定使用并行方法来加快速度,结果如下:

std::future<std::vector<double>> EMX_Counter::getEmxEfficiency()  {
        return std::async([*this]() {
            std::vector<double> temp;               

            std::for_each(std::execution::par, WiresList.begin(), WiresList.end(), [&](auto& PolyObject) {
                double result = PolyObject->getPartialEfficiency();
                //more time-expensive operations
                temp.push_back( result );
            });

            return temp;
        });
    }

调用PolyObject-&gt;getPartialEfficiency();返回一个double并且不抛出异常,它是“安全的”。


我正在使用最新的 Visual Studio 版本(昨天更新)和标志 /std:c++17。问题是我收到此错误:

 std::unique_ptr<WireBase,std::default_delete<_Ty>>::unique_ptr(const
 std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to
 reference a deleted function (file: xmemory0).
  • 这可能是什么?
  • 我在 lambda 中捕获了[*this],所以我有一个对象的副本,我确信(是吗?)异步执行不会有问题。我应该改为按参考值捕获吗?

for_each lambda 中,我通过引用捕获,因为 temp 在范围内,我不会遇到它被销毁的问题。

【问题讨论】:

  • "我已经在 lambda 中捕获了 [*this],所以我有一个对象的副本" 这正是问题所在。 std::unique_ptr的copy-constructor被删除,复制std::vector&lt;std::unique_ptr&gt;的行为需要std::unique_ptr的copy-constructor可用。
  • 您的 unique_ptr 不是唯一的!把它改成 shared_ptr 就可以了
  • EMX_Counter(const std::vector&lt;std::unique_ptr&lt;WireBase&gt;&gt;&amp; w) : WiresList(w) {} 这已经不行了,因为您尝试将unique_ptr 实例从参数复制到您的列表中。
  • 如果你解决了编译问题,请注意你有一个数据竞争:多个线程在没有同步的情况下推送到 temp 向量。
  • 终身问题; std::future&lt;std::vector&lt;double&gt;&gt; getEmxEfficiency() 的返回值是否应该在 EMX_Counter 被销毁后仍然有效?

标签: c++ c++17


【解决方案1】:

我应该改用这段代码:

//global
auto mymutex = std::mutex{};

std::future<std::vector<double>> EMX_Counter::getEmxEfficiency()  {
    return std::async([=]() {
        std::vector<double> temp;               

        std::for_each(std::execution::par, WiresList.begin(), WiresList.end(), [&](auto& PolyObject) {

            //your code...

            auto lock = std::lock_guard<std::mutex>{ mymutex };
            temp.push_back( result );
        });

        return temp;
    });
}

其中WiresList 被声明为std::vector&lt;std::shared_ptr&lt;WireBase&gt;&gt;。现在变量被保护了,我没有更多的编译时间问题,因为有一个共享指针!

【讨论】:

  • 未使用的全局变量?嗯,真的,建议一个全局变量似乎是一个糟糕的计划。
  • 那么现在,一个全局变量保护对单个类中单个互斥体中的单个向量执行的操作?你到底为什么要在那里使用全局变量?
猜你喜欢
  • 2018-08-20
  • 2011-05-09
  • 2011-01-02
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 2018-02-15
相关资源
最近更新 更多