在单个调用C++ 11中启动多个线程

Apa*_*ram 2 c++ multithreading c++11

我理解在C++ 11中创建多个线程的典型方法是:

int num_threads = 10;
std::thread threads[num_threads];
for(int i = 0; i < num_threads; ++i)
{
    threads[i] = std::thread(doSomething);
}
// Call join if you need all threads completion
for(int i = 0; i < num_threads; ++i)
{
    threads[i].join();
}
Run Code Online (Sandbox Code Playgroud)

是否可以一次性启动线程,而不是使用循环来顺序启动每个线程.我知道在CUDA中,线程是同时启动的,没有必要单独启动每个线程.想知道C++ 11中是否有类似的东西可行.

Yak*_*ont 5

是的,您可以生成一个操作,该操作将n在一个语句中启动线程(逻辑上,逻辑上).

template<class F>
std::future<void> launch_tasks( F&& f, size_t n ) {
  if (n==0) { // ready future case, launch 0 threads:
    std::promise<void> p;
    p.set_value();
    return p.get_future();
  }
  std::vector<std::future<void>> results;
  results.reserve(n-1);
  for (size_t i = 0; i < n-1; ++i) {
    results.push_back(
      std::async(
        std::launch::async,
        f, i
      )
    );
  }
  // last thread waits on the previous threads before finishing:
  return std::async(
    std::launch::async,
    [results=std::move(results),f=std::forward<F>(f)]{
      f(results.size());
      for (auto&& others:results)
        others.wait();
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

只需调用launch_tasks( [](size_t i) { /* code */ }, n )将启动n任务,每个任务都给出一个索引.返回的未来将阻止正在完成的所有任务,而不使用额外的线程来完成该任务.

这是为最后一个lambda使用C++ 14特性(广义捕获).你可以编写一个这样的函数对象:

template<class F>
struct work_then_wait {
  F f;
  std::vector<std::future<void>> futures;
  void operator()()const{
    f(futures.size());
    for (auto&& f:results)
      f.wait();
  }
};
Run Code Online (Sandbox Code Playgroud)

然后

return work_then_wait<typename std::decay<F>::type>{
  std::forward<F>(f),
  std::move(results)
};
Run Code Online (Sandbox Code Playgroud)

而不是lambda,它是等价的,但用C++ 11编写.

一个更简单的版本用于std::async( std::launch::deferred等待所有期货的任务,但是这使得wait_until和其他定时等待返回的future无用.