12

並列化できる C++ プログラムがあります。Visual Studio 2010、32 ビット コンパイルを使用しています。

要するに、プログラムの構造は次のとおりです

#define num_iterations 64 //some number

struct result
{ 
    //some stuff
}

result best_result=initial_bad_result;

for(i=0; i<many_times; i++)
{ 
    result *results[num_iterations];


    for(j=0; j<num_iterations; j++)
    {
        some_computations(results+j);
    }

    // update best_result; 
}

それぞれsome_computations()が独立しているため (一部のグローバル変数は読み取られますが、変更されたグローバル変数はありません)、内側のforループを並列化しました。

私の最初の試みはboost::threadでした、

 thread_group group;
 for(j=0; j<num_iterations; j++)
 {
     group.create_thread(boost::bind(&some_computation, this, result+j));
 } 
 group.join_all();

結果は良好でしたが、もっと試してみることにしました。

OpenMPライブラリを試してみた

 #pragma omp parallel for
 for(j=0; j<num_iterations; j++)
 {
     some_computations(results+j);
 } 

boost::thread結果は's のものより悪かった。

次に、pplライブラリを試して使用しましたparallel_for()

 Concurrency::parallel_for(0,num_iterations, [=](int j) { 
     some_computations(results+j);
 })

結果は最悪でした。

私は、この振る舞いが非常に驚くべきものであることに気付きました。OpenMP と ppl は並列化用に設計されているため、boost::thread. 私が間違っている?

boost::threadより良い結果が得られるのはなぜですか?

4

2 に答える 2

10

OpenMP や PPL は悲観的ではありません。言われたとおりに実行しますが、ループを並列化しようとする場合に考慮すべき点がいくつかあります。

これらをどのように実装したかを確認しないと、本当の原因が何であるかを判断するのは困難です。

また、各反復の操作が同じループ内の他の反復に依存している場合、競合が発生し、速度が低下します。関数が実際に何をするかを示していないsome_operationため、データの依存関係があるかどうかを判断するのは困難です。

真に並列化できるループは、各反復を他のすべての反復から完全に独立して実行できる必要があり、どの反復でも共有メモリにアクセスする必要はありません。したがって、ローカル変数に何かを書き込んでから、最後にコピーすることをお勧めします。

すべてのループを並列化できるわけではなく、実行する作業のタイプに大きく依存します。

たとえば、並列化に適しているのは、画面バッファーの各ピクセルで実行される作業です。各ピクセルは他のすべてのピクセルから完全に独立しているため、スレッドはループの 1 回の反復を実行し、反復間のループ内で共有メモリやデータの依存関係を待機する必要なく作業を実行できます。

また、連続した配列がある場合、この配列の一部がキャッシュ ラインにある可能性があります。また、スレッド A で要素 5 を編集してからスレッド B で要素 6 を変更すると、キャッシュの競合が発生する可能性があり、これも速度を低下させます。 、これらは同じキャッシュラインに存在するためです。偽の共有として知られる現象。

ループの並列化を行う際には、考慮すべき多くの側面があります。

于 2013-03-04T16:44:11.017 に答える
3

つまり、openMP主に共有メモリに基づいており、タスク管理とメモリ管理の追加コストがかかります。ppl一般的なデータ構造とアルゴリズムの一般的なパターンを処理するように設計されているため、複雑なコストが追加されます。どちらも追加の CPU コストがかかりますが、単純なフォールダウンboostスレッドはそうではありません (boostスレッドは単純な API ラッピングにすぎません)。そのため、どちらもあなたのboostバージョンよりも遅いです。また、計算例は互いに独立しているため、同期がなく、バージョンopenMPに近いはずです。boost

これは単純なシナリオで発生しますが、データ レイアウトとアルゴリズムが複雑な複雑なシナリオでは、コンテキストに依存する必要があります。

于 2013-03-09T15:14:48.210 に答える