多次并行调用函数

时间:2012-04-18 20:48:25

标签: c++ c multithreading fork

我想多次调用具有不同arg值的函数。为了使执行更快,我想调用函数而不考虑它的实现。

在循环中我将arg传递给函数并调用它现在我的程序不应该等待函数执行并再次循环,相反它不应该认为函数没有完成第一个循环它应该继续并一次又一次地调用该函数,直到循环结束。

如何使用fork和threads来做到这一点,哪一个更快,一个代码框架会有帮助? 让我们说我的函数是void foo(arg1,arg2)

4 个答案:

答案 0 :(得分:2)

如果它是一种计算密集型方法,那么为每次调用生成一个线程/进程并不是一个好主意(事实上,这绝不是一个好主意!)。

您可以使用openmp高效并行化for循环:

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

这将根据可用CPU核心数创建多个线程,然后在它们之间拆分迭代。您可以使用schedule子句进一步调整计划。

答案 1 :(得分:1)

您想要proactor pattern.

的异步实现

以下是一个示例,使用boost::asioboost::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();
}

这里的好处是,如果需要,您可以通过从线程池中调用boost::asio::io_service::run来轻松扩展。

答案 2 :(得分:1)

就像Tudor所建议的那样,我也会使用英特尔TBB或Microsoft PPL中的parallel_for模式算法。

如果你真的想为每个函数生成一个need线程,你可以这样做:

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

}

答案 3 :(得分:0)

github中,有一个仅标头的库,可用于对向量的每个元素异步地调用一次函数。如果函数返回一个值,它将在另一个向量中返回结果。它避免使用被批评的std :: future this CppCon演示文稿中的运行缓慢。另外,可以正常捕获异常。

这里是一个例子:

    #include <iostream>
    #include "Lazy.h"

    template <class T1, class T2>
    double foo(T1 t1, T2 t2) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        return double(t1) + double(t2);
    }


    int main() {
        constexpr int maxThreads = 16; // 0 means as many threads as there are cores

        // Make an input vector
        std::vector<std::pair<int, float>> vecIn;
        for(int i=0; i < 5; ++i)
            vecIn.push_back({10 * i, 1.1 * (i+1)});

        try {
            auto vecOut = Lazy::runForAll<maxThreads>(vecIn,
                            [](auto in){ return foo(in.first, in.second); });

            for (auto i = 0; i < vecOut.size(); ++i)
                std::cout << "foo(" << vecIn[i].first
                          << ", " << vecIn[i].second
                          << ") = " << vecOut[i] << '\n';
        } catch (...)
        { // Deal with the exception here
        }
    }

    /* Output:
    foo(0, 1.1) = 1.1
    foo(10, 2.2) = 12.2
    foo(20, 3.3) = 23.3
    foo(30, 4.4) = 34.4
    foo(40, 5.5) = 45.5
    */