如何为std :: async修改std :: launch策略?

时间:2017-04-23 17:34:58

标签: c++ asynchronous parallel-processing c++14 launch

假设我想在我的c ++代码中使用std::async并行运行一个计算量很大的函数func。现在因为它是一个繁重的功能,我们可能首先使用std::launch::deferred策略,因为情况是我们可能根本不需要运行。

但是,如果我们将来需要突然执行它们,我们希望并行运行。那么我们如何在之后修改std::launch政策。

[嗯,有人可以说,为什么你突然创建std::async,因为突然你需要执行。但我假设我不能这样做。]

或者,除了使用std::async之外,还有更好更清洁的方法吗?

非常感谢任何帮助。提前谢谢。

#include <future>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <iostream>

std::vector<double> func(size_t n) // a computationally heavy function
{
    std::vector<double> vec(n);
    std::generate_n(vec.begin(), n, std::rand);
    return vec;
}

int main()
{
    // create asyncs, now deferred for lazy execution
    auto v1 = std::async(std::launch::deferred, func, 200); // deferred for lazy execution
    auto v2 = std::async(std::launch::deferred, func, 250); // deferred for lazy execution

    // only after sometime we decide to execute both of them
    // but we also now want them to execute in parallel

    // so how can we now change the launch policy?

    // to get the values as quickly as can be
    auto n1 = v1.get().size();
    auto n2 = v2.get().size();

    std::cout<<"Got "<<n1<<" and "<<n2<<" random numbers in parallel!"<<std::endl;
    return 0;
}

更新

多思考一点可以解决这个问题:

使用std::async定义std::launch::deferred后,当一个人调用.get()函数时,是否保证运行 async (即并行)当然,不是。 http://en.cppreference.com/w/cpp/thread/launch

  

它在调用线程上执行。

然后 async 的概念被破坏了,对吧?

1 个答案:

答案 0 :(得分:1)

如果std::async使用std::launch::deferred,则会在调用返回的std::future对象的get()函数时运行。

这表明您可以强制std::launch::async这样:

int s1 = 0;
int s2 = 0;

auto v1 = std::async(std::launch::deferred, []{ return 1; });
auto v2 = std::async(std::launch::deferred, []{ return 2; });

// some fancy coding ...

if(need_to_upgrade_launch_policy())
{
    auto v1a = std::async(std::launch::async, [&]{ return v1.get(); });
    auto v2a = std::async(std::launch::async, [&]{ return v2.get(); });

    s1 = v1a.get();
    s2 = v2a.get();
}

//  more clever coding ...

if(v1.valid()) // was never upgraded
    s1 = v1.get();

if(v2.valid()) // was never upgraded
    s2 = v2.get();