On Mittwoch, 22. Juni 2016 16:24:01 CEST Michael Levine wrote:
> I’m looking for some advice regarding creating an
> std::vector<hpx::future<std::vector <int> > > where the elements of the
> innermost vector use a random number generator.
> 
> 
> 
> Typically, if I were to use to generate this vector of random integers, I’d
> use either boost or standard library random functions (or possibly Intel MKL
> / VSL); however, all of these RNGs have a state.  As I understand, a naïve
> implementation, just passing a reference to the RNG state would lead to
> race conditions and will result in the RNG state ending up in some
> undefined-state.  If I understand correctly, that would be the reason that
> an action cannot have a non-const reference parameter.

The reason why actions can't take non-const references is because those don't 
make a lot of sense in a distributed context. const references are fine, but 
the parameters you pass to async will get decay-copied into the packaged task 
anyway.

> 
> 
> 
> In light of this, how could I use a future to represent this vector of
> future integer-vectors?  Is there any way to make this code concurrent?

One possibility would be to create a thread local random number generator as 
suggested here:
http://stackoverflow.com/questions/21237905/how-do-i-generate-thread-safe-uniform-random-numbers

The other is of course to really construct a fully parallel number generator.

> 
> As a rough reference:
> 
> #include <random>
> #include <vector>
> #include <hpx/hpx.hpp>
> #include <hpx/include/future.hpp>
> #include <hpx/include/async.hpp>
> #include <hpx/hpx_main.hpp>
>
> using random_vec_t = std::vector<int>;
> 
> constexpr int random_vec_size = 8;
> constexpr int vec_random_size = 30;
> 
> //template <typename RNG>
> std::vector<random_vec_t> Generate_Random_Vector(std::mt19937_64 &rng) {
>   std::vector<random_vec_t> random_vector_set;
>   static const int range_ = 100;
>  std::uniform_int_distribution<int> dist_(0, range_);
>   random_vector_set.resize(vec_random_size);
> 
>   for (auto &vec : random_vector_set) {
>     vec.reserve(random_vec_size);
>     for (int i = 0; i < random_vec_size; ++i)
>       vec.push_back(dist_(rng));
>   }
>   return random_vector_set;
> }
> 
> HPX_PLAIN_ACTION(Generate_Random_Vector, generate_random_vector_action); //
> <= this line fails with message: static_assert failed "Using non-const
> references as arguments for actions is not supported."

Makes sense, as explained above.

> int main(int argc, char *argv[]) {
>   std::mt19937_64 rng_;
>   hpx::future<std::vector<random_vec_t>> future_vectors_ =
> hpx::async(generate_random_vector_action, rng_);

Is there any reason to use an action here? async can just take any callable 
(including regular function pointers). You could express what you have like 
this:

async(&generate_random_vector, std::ref(rng_));

> 
>   auto vecs_ = future_vectors_.get();
> 
>   for (auto outer_vec : vecs_) {
>     for (auto inner_vec : outer_vec)
>       std::cout << inner_vec << "\t";
>     std::cout << std::endl;
>   }
> 
>   return 0;
> }
> 
> Thanks and regards,
> 
> Shmuel


_______________________________________________
hpx-users mailing list
hpx-users@stellar.cct.lsu.edu
https://mail.cct.lsu.edu/mailman/listinfo/hpx-users

Reply via email to