2016-08-17 8 views
3

いくつかのスレッドが動作しているので、処理する前にすべてのスレッドが特定のポイントに達したことを保証する必要があります。私はある種の障壁を実装する必要があります。複数のスレッドから実行することができる機能funcを考えてみましょう:スレッド間の同期障壁を実現する最良の方法は何ですか

void func() 
{ 
    operation1(); 
    // wait till all threads reached this point 
    operation2(); 
} 

必要に応じてブーストを考慮すると、C++ 11とVS12を使用して、この障壁を実現するための最良の方法は何ですか。

+0

簡単な方法は、2つの異なる機能に作業を分けることです。メインスレッドでは、最初の半分を実行するスレッドを作成し、それらのすべてを結合し、後半を実行します。 – Zereges

+0

これは実際に複雑になるでしょう。私の建築は私に仕事を分けることを許しません。 – GregPhil

+1

これにはbarrierという実際のスレッドプリミティブがあります。私はpthreadがこれを実装していることを知っています。また、boostはこれを実装します。 –

答えて

1

オプションはOpenMPフレームワークを使用できます。

#include <omp.h> 

void func() 
{ 
    #pragma omp parallel num_threads(number_of_threads) 
    { 
    operation1(); 

    #pragma omp barrier 
    // wait till all threads reached this point 

    operation2(); 
    } 
} 

あなたは残念ながらboost::barrier
を使用することができます-fopenmp

+0

はおもしろいですが、ompの使い方についてのドキュメントやリファレンスはありますか? – GregPhil

+0

入門チュートリアルはここにあります。[openmpチュートリアル](http://bisqwit.iki.fi/story/howto/openmp/)、参考文献はこちら[openmp reference](https://computing.llnl.gov/tutorials/) openMP /)。優秀なフォーラムはここにあります[openmp forum](http://openmp.org/forum/) – tnas

+0

それは移植性がないと聞きます – Zereges

4

でコードをコンパイルし、スレッドのバリアコンセプト自体はC++ 11またはVisual C++の一部ではありません。
純粋なC++ 11では、condition variableとカウンタを使用できます。

class my_barrier 
{ 

public: 
    my_barrier(int count) 
    : thread_count(count) 
    , counter(0) 
    , waiting(0) 
    {} 

    void wait() 
    { 
     //fence mechanism 
     std::unique_lock<std::mutex> lk(m); 
     ++counter; 
     ++waiting; 
     cv.wait(lk, []{return counter >= thread_count;}); 
     --waiting; 
     if(waiting == 0) 
     { 
      //reset barrier 
      counter = 0; 
     } 
     lk.unlock(); 
    } 

private: 
     std::mutex m; 
     std::condition_variable cv; 
     int counter; 
     int waiting; 
     int thread_count; 
}; 

my_barrier barrier; 

void func() 
{ 
    operation1(); 
    barrier.wait(); 
    operation2(); 
} 

述語が満たされるまで各スレッドが待機します。最後のスレッドは述語を有効にし、待機中のスレッドを続行させます。 バリアを再利用する場合(たとえば、関数を複数回呼び出すなど)、別の 変数が必要で、カウンタをリセットする必要があります。

この現在の実装には制限があります。 func();func();を2回呼び出しても、スレッドは2回目の待機を行わないことがあります。

+0

Thxたくさん...簡単で非常に有望です! – GregPhil

+0

あなたの実装例では 'wait'を実装しています。 2つのスレッドの障壁を想像してみましょう。そして、両方とも 'wait'を呼び出します。スレッドが2番目のカウントを待っている間に進行します。しかし、第1のカウントのために「待機」したスレッドは、決して目覚めされない(「通知される」)ので、理論的には永遠に待つことができる。 – WhiZTiM

関連する問題