2

arg の値が異なる関数を何度も呼び出したい。実行を高速化するために、実装を考慮せずに関数を呼び出したいと思います。

ループ内で、引数を関数に渡して呼び出します。プログラムは、関数が実行されて再びループするのを待つべきではありません。代わりに、最初のループで関数が完了していないと見なすべきではありません。ループが終了するまで何度も機能します。

これを行うためにフォークとスレッドを使用する方法、どちらがより速く、コードのスケルトンが役立ちますか? 私の関数が void foo(arg1,arg2) であるとしましょう

4

4 に答える 4

2

それが計算集約的な方法である場合、呼び出しごとにスレッド/プロセスを生成することはお勧めできません (実際のところ、それは決して良い考えではありません!)。

openmp を使用して for ループを効率的に並列化できます。

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

これにより、使用可能な CPU コアの数に応じて多数のスレッドが作成され、それらの間で反復が分割されます。schedule句を使用して、スケジューリングをさらに調整できます。

于 2012-04-18T20:52:39.443 に答える
1

Tudorが推奨しているように、parallel_forIntelTBBまたはMicrosoftPPLのパターンアルゴリズムも使用します。

すべての関数に必要なスレッドを本当に生成したい場合は、次のように実行できます。

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

}
于 2012-04-18T21:03:58.933 に答える
1

proactor パターンの非同期実装が必要です。

boost::asioと を使用した例を次に示し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();
}

ここでの利点は、boost::asio::io_service::run必要に応じてスレッドのプールから呼び出すことで簡単にスケーリングできることです。

于 2012-04-18T20:55:38.413 に答える
0

githubには、ベクターの要素ごとに 1 回非同期で関数を呼び出すために使用できるヘッダーのみのライブラリがあります。関数が値を返す場合、別のベクトルで結果を返します。たとえばこのCppCon プレゼンテーションで遅いと批判されている std::future の使用を回避します。また、例外は正常にキャッチできます。

次に例を示します。

    #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
    */
于 2020-10-28T12:08:16.780 に答える