简体   繁体   中英

Launching Multiple Threads in a single call C++ 11

The typical way to create multiple threads in C++ 11 as I understand is:

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();
}

Is it possible to launch the threads in one shot, instead of using a loop to start each thread sequentially. I know in CUDA, threads are launched simultaneously and there is no need to start each one individually. Wondering if something similar is possible in C++ 11.

Yes, you can generate an operation that will launch n threads (well, logically) in one statement.

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();
    }
  };
}

simply call launch_tasks( [](size_t i) { /* code */ }, n ) will launch n tasks, each given an index. The future that is returned will block on all of the tasks being completed, without using an extra thread for that task.

This is using a C++14 feature (generalized capture) for the last lambda. You can write a function object like this:

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();
  }
};

then

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

instead of the lambda and it is equivalent, but written in C++11.

A simpler version uses std::async( std::launch::deferred on a task that waits on all the futures, but that makes wait_until and other timed waits on the returned future useless.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM