imneme / pcg-cpp

PCG — C++ Implementation
Apache License 2.0
723 stars 98 forks source link

Can I store pcg32 as a class member? #10

Open alberto-santini opened 8 years ago

alberto-santini commented 8 years ago

I'd like to store my rng as a class member, as I have many methods that require it in my class. Something like:

class MyClass {
  pcg32 rng;
  // ...
  MyClass() : rng(pcg_extras::seed_seq_from<std::random_device>{}) {}
}

leads to segfaults when I use, e.g. std::uniform_real_distribution with rng. I believe this is due to the fact that somewhere it tries to access a reference to the seed sequence, that was built in-place in the constructor! I'm not sure how to go around this... as you know, you can't store an std::random_device, because its copy constructor is deleted. Can you provide a minimal example of how to use pcg "in oo-programming", or at least with classes and not just within main()?

imneme commented 8 years ago

Thanks for the report. I'll look into it!

alberto-santini commented 8 years ago

Hi. Thanks for your reply. I provide more information on what happens.

I have a small programme that uses pcg and I store a pcg32 object in my class, as described in the previous post. Some methods of the class use the object at various times and they can even pass it to an external helper function (I tried to pass it both by reference and by value and I saw no difference wrt the faulty behaviour).

At some point, when the rng is used by a std::uniform_real_distribution, the progamme crashes with either a segfault or a bus error.

I tried to reproduce this problem in a smaller, cleaner source file in this gist. Unfortunately (or, rather, fortunately) everything seems to work well in this small example. I store the pcg32 object in the class. I initialise it in-place in the constructor with a random sequence provided by seed_seq_from<std::random_device> and I keep using it with std::uniform_real_distributions and std::normal_distributions over and over, without any problem.

Therefore, in order to give a reproducible version of the bug, I have to link to the original programme. It's not so much bigger than the previous gist, as it contains only 2 files, but it might be a bit harder to follow, as the use of pcg is just a small part of it. It is, in fact, a very basic framework for genetic algorithms and can be found in this gist.

The first two files in the gist (debug_1.txt and debug_2.txt) show gdb output when the bus error and segfault happen. The problems seem to lie in std::mersenne_twister_engine in random.tcc.

I hope this can help to shed light on the usage of pcg and its robustness, even if it's not clear to me yet if the problem lies with <random>, pcg or (perhaps more likely) my usage of them.

alberto-santini commented 8 years ago

All right, I think I got it! The problem is apparently due to my mixing pcg32 in ga.hpp with std::mt19937 in test.cpp. If I change main.cpp to also use PCG and drop std's random generators, the problem disappears!

Is this, somehow, intended?