0

各スレッドが const 関数オブジェクトを呼び出す Intel TBB を使用しています。コードは次のとおりです

#include "process_edge.hpp"
// process a vertex in graph
template <typename Graph, typename time>
struct my_func{ 
 public:
  my_func() {  } 
  my_funct(Graph& _G, time _t) : G(_G), t(_t) { } 

  template <typename vertex_t>
  void operator()( vertex_t  vertex ) const { 

    boost::tie (boeit, eoeit) = boost::out_edges(vertex, G);  //get out_edge_iterators 
    for_each(boeit, eoeit, process_edge<Graph>(G)); //for each out_edge_iterator ---> process_edge functor  

  }
 private: 
   Graph& G;
   time t;
 };


  //process_edge.hpp file
  //process edge function object uses a random number generator (uniform real (0,1)

  #include "unif_real.hpp"  // uniform random generator class (see below)

  template <tyepname Graph>
  struct process_edge{
   public:
    process_edge() { }
    process_edge(Graph& _G) : G(_G), rnd(0,1) {  }

   template <typename edge_t>
   void operator() (edge_t edge) const { 

    if(rnd().generate() > 0.5)
       //do something with edge
  } 
 private
  Graph& G;
  uniformReal rnd;
 };


 //uniformReal.hpp  //random number generator class 
class uniformReal {
 public:
   uniformReal (int a, int b)
     :  range(a,b)
     {
       initialize();
      }

  void initialize() const {
    struct timeval t;
    gettimeofday(&t, 0);
    xsubi[0] = time(0);
    xsubi[1] = t.tv_usec ^ t.tv_sec;
    xsubi[2] = t.tv_usec ^ t.tv_sec * time(0);
  }


   inline double generate() const {
     initialize();
     return  erand48(xsubi);
   }

  private:
   mutable unsigned short int xsubi[3];
  };




 //call the parallel_for_each for vertex 
 tbb::parallel_for_each(vertex_begin, vertex_end, my_func<Graph,int>(G, t));

プログラム フローは次のように説明され
ますtbb::parallel_for_each(vertex_begin, vertex_end, my_func<Graph, int>(G, t));
。my_func 内で、各スレッドは頂点の out_edge_iterator 範囲を計算します。
3) 各スレッドは次のことを行います: 各エッジの process_edge 関数オブジェクト:
std::for_each(out_edge_begin, out_edge_end, process_edge<graph>(G));
4) 関数オブジェクト process_edge には乱数ジェネレーター (0,1) があります。

私の質問は次のとおり
です。乱数ジェネレーターのスレッドは安全ですか? 時々間違った結果が出るからです。答えは生成される乱数に依存しますが、乱数
ジェネレーター クラスがスレッド セーフかどうかはわかりません。

同じ乱数が生成されるように、同じシードを使用したいとします。
どうすればそれを達成できますか?
スレッドセーフな乱数ジェネレータークラスを生成する際に少し混乱します

スレッドセーフな乱数を使用したい場合、tbb::parallel_for_each()
どうすればよいですか? 乱数ジェネレーター クラス オブジェクトには const 関数が含まれている必要があります。そうしないと、関数オブジェクトに operator()() を const として含める必要があるという TBB の制限により、コンパイラ エラーが発生します ...

つまり、私の質問は次のとおりです
。1)TBBでスレッドセーフな乱数ジェネレーターを使用します。上記の乱数ジェネレーターをより効率的にすることはできますか?
2)静的(同じシード)にすることはできますが、スレッドセーフにすることはできますか?もしそうなら、アイデアが必要なだけで、自分で実装できます。
3) tbb::parallel_for_each() でスレッドセーフな乱数ジェネレーターを使用するためのアイデア
4) この場合、ブースト変量ジェネレーターを使用できますか? 統一された Real クラスでエンジンとディストリビューションを定義し、それらを組み合わせて generator() オブジェクトを取得します

不明な点がある場合は、同じことを明確にしますのでお知らせください。

4

1 に答える 1

0
  1. ライブラリ Boost.Random http://www.boost.org/doc/libs/1_55_0/doc/html/boost_random.htmlを使用して、スレッドセーフでコピー可能な乱数ジェネレーターを取得できます。

  2. あなたのコードにはすでにこの const-ness 問題があります (operator() は const であるべきですが、事実上はそうではありません)。標準的な C++ の方法で解決します。一部のメンバーは として宣言されmutableます。クラスclass uniformRealでそれを行いました.Boost.Randomを使用すると、ジェネレーター全体を次のように宣言できます.mutable

于 2014-06-27T21:31:48.607 に答える