0

I am using Intel TBB where each thread calls a const function object. the code is as follows

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

Program Flow is explained as below: (assume 8 threads and 8 vertex in parallel --> assume)
1) tbb::parallel_for_each(vertex_begin, vertex_end, my_func<Graph, int>(G, t));
2) each thread calls my_func. Inside my_func, each thread computes a an out_edge_iterator range for the vertex.
3) each thread does the following: process_edge function object for each edge:
std::for_each(out_edge_begin, out_edge_end, process_edge<graph>(G));
4) the function object process_edge has a random number generator (0,1) As above.

My questions is:
Is the random number generator thread safe? Because I sometimes get erroneous results. Although the answer is depending upon the random number generated
I am not sure my random number generator class is thread safe or not.

Suppose I want to use the same seed so that same random number is generated.
How do I achieve that?
I get a bit confused in generating thread safe random number generator class

If suppose I want to use a thread safe random number in tbb::parallel_for_each()
how do i do that? My random number generator class object must contain const functions, else I get compiler error because of TBB restricts that function object should contain the operator()() as const ...

So in short my questions are the following:
1) using thread safe random number generator in TBB. Can the above random number generator be made more efficient ?
2) can I make it static (same seed) but thread safe ? If so I just need some idea, I can implement it on my own.
3) any ideas to use thread safe random number generator in tbb::parallel_for_each()
4) Can I somehow use boost variate generator in this case? define engine and distribution in the uniform Real class and combine them to get a generator() object

If anything is not clear, please let me know I will clarify the same.

pugs
  • 155
  • 1
  • 8
  • 1
    It's not thread safe, because `erand48()` isn't - give each thread has its private `xsubi` or something, and don't initialize the generator every time! – loreb Jun 25 '14 at 14:10

1 Answers1

0
  1. You can use the library Boost.Random http://www.boost.org/doc/libs/1_55_0/doc/html/boost_random.html to get thread-safe copyable random number generators.

  2. You code already have this const-ness problem (operator() should be const but de-facto is not). One solves it in standard C++ way: some members are declared as mutable. You did that in the class class uniformReal, with Boost.Random you can declare your whole generator as mutable

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24