rand()在通过函数调用时生成相同的随机数集(即使在使用srand(time(NULL)进行种子设定之后)

rand() generating same set of random numbers when called through functors (even after seeding with srand(time(NULL))

本文关键字:NULL time srand 种子 之后 随机数 函数调用 rand      更新时间:2023-10-16

我在生成随机数方面有问题,我已经阅读了关于SO的大多数关于这个主题的帖子,但似乎没有一个解决方案有效。在将其标记为重复之前,请仔细阅读

我有一个函子来生成0.5到-0.5之间的随机数:

struct randomize
{
__host__  void operator()( double &x ) const {
x=(double) (rand() % 1000000) / 1000000 - 0.5;
}
};

我通过for_each这样打电话:

thrust::for_each(myVector.begin(),myVector.end(),randomize());

它又在类的构造函数(比如myClass)中被调用,该类被调用为:

myObjs=std::vector<myClass>(20,myClass(no_of_inputs));

问题是所有myClass' objects are filled with the same set of values. These values change with each run but are the same across allmyVectors`中的所有myVector

我知道rand()是一个伪随机数生成器,不能指望它生成的数字是真正随机的。。但这太巧合了。

只是澄清一下:

  • 在整个程序中,我只调用srand(time(NULL))一次
  • 我使用的是thrust::for_each,而不是std::for_ech,但这应该没有多大区别
  • 我知道随机化函子远非完美,但我正在修改并除以1000000,以便得到小数点后的6位数。如果你能指出一个更好的方法,那就太好了,但请不要被它冲昏头脑
  • 我现在不能使用c++11或boost
  • 我不能为myClass使用默认构造函数
  • 一个不需要我过多更改代码结构的解决方案将不胜感激
myObjs=std::vector<myClass>(20,myClass(no_of_inputs));

您是否为myClass定义了一个随机数据的复制构造函数?(然而,在我看来,这将违背复制构造函数的目的)

如果不是,则将相同的myClass复制到myObj中20次,并且vector<myClass>将通过调用每个元素的默认复制构造函数来构造,而该构造函数反过来将简单地复制myVector中的数据。

问题是所有myClass对象中的所有myVector都填充了相同的值集。

这是因为std::vector<myClass>(20, myClass(no_of_inputs))为您提供了一个临时对象的20个副本。

如果为myClass提供默认的ctor,则可以跳过第二个参数到vector-ctor
您还可以一个接一个地push_backmyClass对象。

这给我们带来了建议:

我看到你的randomize::operator()标记为__host__,那么没有理由使用thrust::for_each来支持std::for_each

我不能使用c++11(目前)或提升(根本)

但是您可以使用tr1扩展,它还提供<random>-头:

#include <tr1/random>
template <typename T>
struct twisterize {
const T min;
const T max;
twisterize(const T & min, const T & max) : min(min), max(max) {}
void operator()(T & x) {
typedef std::tr1::mt19937 rng_t;
typedef std::tr1::uniform_real<T> dist_t;
static rng_t rng( ((std::tr1::random_device())) ());//most vexing parse, yikes
static dist_t dist(min, max);// [min,max) for real distributions
static std::tr1::variate_generator<rng_t, dist_t> bound_dist(rng, dist);//not necessary in c++11
x = bound_dist();//using the c++11 way `dist(rng)` produces unexpected results with tr1
}
};

由于函子现在有状态,您最好为它创建一个变量,并将其传递给for_each:
twisterize<double> rand_functor(-0.5, 0.5);

如果你真的想在gpu上生成随机数,请看这里

在ENTIRE代码中多次调用srand永远不会让任何事情变得更好[当然,除非你真的想用相同的随机数序列重复另一次运行]。

你得到的实际数字将取决于种子。由于time()从一秒到下一秒只会发生一点变化,即使您等待几分钟,也只有最后几位数字会发生变化。你可能会发现,使用不同的时间源(例如,一个给你毫秒或更小的时间源),并将其与time的结果相结合,会给你一个更好的随机数。然而,如果您需要非常可移植的代码,这将有点尴尬。

[当然,有很多聪明的方法可以获得一个不需要时间的"随机种子",但它们往往有点复杂、不可移植和/或速度较慢——例如,你可以将"今天的日期"发送到谷歌的搜索页面,并对返回的HTML进行哈希处理。几乎可以肯定的是,每次这样做都会产生不同的结果]。

我只调用srand(时间(NULL))一次。

不,您说过要在类构造函数中调用它,所以每次创建实例时都会调用它。每次发生这种情况时,伪随机序列都会被重置(重置为相同的序列,因为这一切都在一秒钟内运行,因此种子不会改变),然后就会发生这种情况。

在整个程序中只调用它一次