似乎std::async
的默认行为非常有利于std::launch::deferred
。我试图理解为什么默认行为似乎永远不会实际产生异步任务。请考虑以下代码:
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <vector>
int main(void)
{
std::vector<std::future<void>> task_list;
size_t n_tasks = 10; // Let's say this could change at runtime
// The first two seem interchangeable in this example:
//auto launch_pol = std::launch::deferred;
//auto launch_pol = std::launch::async | std::launch::deferred;
// Only this seems to actually do async tasks:
auto launch_pol = std::launch::async;
auto start_time = std::chrono::steady_clock::now();
// Generate a bunch of tasks
for (size_t i = 0; i < n_tasks; i++) {
task_list.emplace_back(std::async(launch_pol,
[i](){
std::cout << " Starting task " << i << std::endl;
// The sleep is emulating, for example, a slow, I/O
// bound operation
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << " Stopping task " << i << std::endl;
}
));
// The following lines are experiments I tried to nudge the
// task to start doing something.
if (!task_list.at(i).valid()) {
std::cout << "Task not valid!" << std::endl;
}
task_list.at(i).wait_for(std::chrono::milliseconds(1));
}
// Wait for them to complete
for (auto& task : task_list) {
task.get();
}
std::chrono::duration<double> stop_time =
std::chrono::steady_clock::now() - start_time;
std::cout << "Execution time: " << stop_time.count() << std::endl;
return 0;
}
请注意,我一直在试验多个启动策略。似乎除非我明确地陈述std::launch::async
(仅!),否则编译器将回退到std::launch::deferred
。我尝试使用Clang 3.8,gcc 5.4,而this post似乎表明MSVC以相同的方式工作。
好的,这与C ++标准并不矛盾。我知道这不是一个bug。如果我们指定deferred
,我们可能会得到延迟评估,这(在这种情况下)与我的任务的串行执行几乎相同。但是,如果编译器只回到std::launch::deferred
?
如果编译器总是回退到懒惰评估,那么在没有std::async
的情况下调用std::launch::async
似乎毫无意义。如果我使用默认的启动策略,我希望C ++运行时在启动线程时是否聪明。
一些背景:在我试图解决的问题中,我正在运行可变数量的初始化调用,这些调用非常慢,但完全受I / O限制(即,它们大部分时间等待结果来自别处)。这些数量可能会扩展,所以我希望从编译器的一些帮助来安排线程。
答案 0 :(得分:2)
编译器供应商基本上都选择了#34;选择一个&#34;意思是&#34;延期&#34;。
这很糟糕。
他们可以自由选择任何逻辑。他们选择让他们的逻辑“始终推迟”。