How can I refactor this code into multi-thread version?

Viewed 219

There is a loop which takes quite a long time and I'm considering refactoring this code into multi-thread version. And here is the model.

   Photon photon;
    for (int i=0;i<1000000;++i){
         func(){
          photon.lanuch(args...){
          // do something  
          }
      }
    }

I have to call this function a thousand and thousand times.So I was wondering how can I create some threads to run this function at the some time. But the photon have to be individual every single time. the index i can be converted to this:

 atomic<int> i{0};
    while(i<1000000){
          func(){
              photon.lanuch(args...){
              // do something  
             ++i;
               }
          }
    }
2 Answers

With threading you have to pay attention to object lifetime and sharing far more than normal.

But the basic solution is

void do_tasks( std::size_t count, std::function<void( std::size_t start, std::size_t finish )> task ) {
  auto thread_count = std::thread::hardware_concurrency();
  if (thread_count <= 0) thread_count = 1;

  std::vector<std::future<void>> threads( thread_count-1 );

  auto get_task = [=](std::size_t index) {
    auto start = count * index / thread_count;
    auto finish = count * (index+1) / thread_count;
    // std::cout << "from " << start << " to " << finish << "\n";
    return [task, start, finish]{ task(start, finish); };
  };
  for( auto& thread : threads ) {
    auto index = &thread-threads.data();
    thread = std::async( std::launch::async, get_task(index) );
  }
  get_task( threads.size() )();
  for (auto& thread : threads) {
    thread.get();
  }
}

This is a little multi threading library.

You use it like this:

do_tasks( 100, [&](size_t start, size_t finish) {
  // do subtasks starting at index start, up to and not including finish
});

There are other more complex threading libraries, but writing a small half-decent one isn't hard so I did it.

To be explicit:

Photon photon;
do_tasks( 1000000, [&](size_t start, size_t finish) {
  for (int i = start; i < finish; ++i) {
    photon.lanuch(args...){
  }
});

but you'll have to be extremely careful making sure there is no unsafe data sharing between the threads, and you aren't just blocking each thread on a common mutex.

Live example

Related