【发布时间】:2014-08-12 03:36:45
【问题描述】:
在不使用 iostream 接口的情况下存储 C++11 随机生成器状态的最佳方法是什么。我想做这里列出的第一个替代方案[1]?但是,这种方法要求对象包含 PRNG 状态且仅包含 PRNG 状态。特别是,如果实现使用 pimpl 模式(至少这可能会在重新加载状态而不是用坏数据加载它时使应用程序崩溃),或者有更多与 PRNG 对象相关联的状态变量没有与生成的序列有关。
对象的大小是实现定义的:
-
g++ (tdm64-1) 4.7.1给了sizeof(std::mt19937)==2504但是 -
Ideonehttp://ideone.com/41vY5j 给 2500
我缺少像
这样的成员函数size_t state_size();const size_t* get_state() const;void set_state(size_t n_elems,const size_t* state_new);
(1) 应返回随机发生器状态数组的大小
(2) 应返回指向状态数组的指针。指针由 PRNG 管理。
(3) 应该从 state_new 指向的缓冲区复制缓冲区std::min(n_elems,state_size())
这种接口允许更灵活的状态操作。或者是否有任何 PRNG:s 的状态不能表示为无符号整数数组?
[1]Faster alternative than using streams to save boost random generator state
【问题讨论】:
-
您可能会发现this question 很有帮助。除此之外,我认为如果不了解底层实现,就不可能序列化 RNG(或任何对象,真的)。如果可能的话,它可能会涉及到一些……古怪的黑客。
-
@MoreAxes 提到的问题是不相关的。此外,这并不是真正的性能问题,而是接口兼容性问题:I/O 接口不是从任何 iostream 类派生的,如果不先复制到 stringstream,然后再转换回二进制,最后,我就无法使用提供的方法使用 ChunkIO::Writer::dataWrite 函数编写它。
-
g++和 Ideone 的sizeof std::mt19937返回值分别比存储 Mersenne Twister 状态数组所需的值大 8 和 4 个字节。如果这在任何一种情况下都是单个值,那么我敢打赌它是一个指针(我假设您使用的是 64 位系统而 Ideone 不是),您需要在序列化过程中相应地处理它。如果它是一个非指针值(或者在g++的情况下是两个),按原样序列化它可能是安全的。 -
您也可以尝试不同的方法:创建一个包装类来存储种子和调用次数,并仅存储这些。在反序列化期间,使用存储的种子为 RNG 播种,并多次调用它。这可能有点奇怪,因为我不确定 C++11 的发行版是否总是从调用它们的 RNG 请求相同数量的伪随机字节,但似乎值得一试。在反序列化过程中显然会很慢,但序列化会非常快。
-
@MoreAxes 它是一个大小值:
_UIntType _M_x[state_size];size_t _M_p;_M_p是状态大小,它也被写入序列化。生成1e6个随机数需要多长时间?