call a function many times in parallel

2019-07-20 08:27发布

问题:

I want to call a function with different value of arg many times. To make the execution faster I want to call the function without considering its implementation.

Inside a loop i pass the arg to the function and call it now my program should not wait for the function to execute and loop again, instead it should not consider that the function has not completed for the first loop it should go ahead and call the function again and again till the loop ends.

how to use fork and threads to do this , which one will be faster and a skeleton of code will help ? Lets say my function is void foo(arg1,arg2)

回答1:

If it's a computationally intensive method then it's not a good idea to spawn a thread/process for each call (as a matter of fact, it's never a good idea!).

You can efficiently parallelize the for loop using openmp:

#pragma omp parallel for
for(int i = 0; i < N; i++)
{
    int arg1 = ...
    int arg2 = ...
    foo(arg1, arg2);
}

This will create a number of threads according to the number of available CPU cores and then split the iterations among them. You can further tune the scheduling using the schedule clause.



回答2:

You want an asynchronous implementation of the proactor pattern.

Here's an example, using boost::asio and boost::thread:

#include <iostream>
using namespace std;

#include <boost/asio.hpp>
#include <boost/thread.hpp>

// your function, with its arguments
void foo(int x, int y)
{
   cout << x << " * " << y << " = " << x * y << "\n";
}

int main()
{
   boost::asio::io_service svc;
   boost::asio::io_service::work w(svc);

   // create a thread to run the io_service proactor
   boost::thread thread(boost::bind(&boost::asio::io_service::run, &svc));

   for(int z = 0; z < 32; ++z)
   {
      // bind the function to its arguments to 
      // be called in the context of the running
      // thread
      svc.post(boost::bind(&f, 2, z));
   }

   boost::this_thread::sleep(boost::posix_time::milliseconds(1000));

   svc.stop();
   thread.join();
}

The benefit here, is you can scale easily by calling boost::asio::io_service::run from a pool of threads if necessary.



回答3:

Like Tudor has recommend, I would also use a parallel_for pattern algorithm from either Intel TBB or Microsoft PPL.

If you really want to spawn a need thread for every function, you can do it like this:

#include <thread>
#include <vector>

void foo(arg1, arg2) {
  //do stuff
}

int main() {

  std::vector<std::thread> threads;

  for(auto i = x; i != y; ++i)
    threads.emplace_back(foo, arg1, arg2);

  for(auto& i: threads)
    i.join();

}