|
Boost Users : |
From: ajb_at_[hidden]
Date: 2005-06-01 20:22:11
G'day all.
"Sliwa, Przemyslaw (London)" <Przemyslaw_Sliwa_at_[hidden]> wrote:
> I have a question which is not related directly to boost.
> I am writing a multithreaded application and would like to make use of
> a multiprocessor machine in order to speed up our Monte Carlo
> simulation engine. We make use of the random number package (random
> number distributions). My question is: making the random number
> generator a global variable (object) it is possible to use it in
> several threads at the same time -> does it mean that the random
> sequences will be repeated and the entire simulation will be simply a
> repetition of n non-random sequences? This can be avoided when a lock
> is acquired on the random number generator and at a given time just
> one thread can access the rng and the advantage of the multiprocessor
> machine is lost. Can you advise?
You might be able to ease the pain by requesting them from the RNG in
blocks and caching them in a thread-local way. The attached code is
untested, but it should give you a general idea. You create a
concurrent_number_generator_adaptor for the RNG, then create a
number_generator_cache for each thread.
Cheers,
Andrew Bromage
--------8<---CUT HERE---8<--------
template<class Generator>
class concurrent_number_generator_adaptor
{
public:
// This class models NumberGenerator, in addition to a get_bulk
// operation which gets a bunch of numbers. (This should probably
// be modelled as a concept in its own right.)
BOOST_CLASS_REQUIRE(Generator, boost, NumberGeneratorConcept);
typedef Generator generator_type;
typedef typename Generator::result_type result_type;
result_type
operator()()
{
Generator& gen = *gen_;
mutex::scoped_lock lck(mut_);
return gen();
}
template<typename It>
void
get_bulk(int num, It out)
{
function_requires< OutputIteratorConcept<It> >();
Generator& gen = *gen_;
mutex::scoped_lock lck(mut_);
while (num-- > 0)
{
*out++ = gen();
}
}
concurrent_number_generator_adaptor(const shared_ptr<Generator> gen)
: gen_(gen)
{
}
private:
mutex mut_;
shared_ptr<Generator> gen_;
};
template<class Generator, int N>
class number_generator_cache
{
public:
// This class models NumberGenerator
BOOST_CLASS_REQUIRE(Generator, boost, NumberGeneratorConcept);
// We also require the get_bulk() operation.
typedef Generator generator_type;
typedef typename Generator::result_type result_type;
result_type
operator()()
{
if (pos_ == cache_.end())
{
gen_->get_bulk(N, cache_);
pos_ = cache_.begin();
}
return *pos_++;
}
number_generator_cache(const shared_ptr<Generator> gen)
: gen_(gen), pos_(cache_.end())
{
}
private:
typedef array<result_type,N> cache_type;
shared_ptr<Generator> gen_;
cache_type cache_;
cache_type::iterator pos_;
};
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net