如何生成线程安全的统一随机数?

我的程序需要在一定范围内生成许多随机整数(intmin,intmax)。每个呼叫将有一个不同的范围。做这件事的好方法(最好是线程安全的)是什么?以下内容不是线程安全的(并且使用rand(),人们似乎不鼓励这种做法):

内部数据(常量内部数据和最小值、常量内部数据和最大值)
{
返回值(rand()%(最大值+1分钟))+min;
}

这是慢得多但使用<随机&gt:

内部数据(常量内部数据和最小值、常量内部数据和最大值){
std::默认随机引擎生成器;
标准:均匀分布(最小值、最大值);
回流分配(发电机);
}

这就是我想要的(尽管changeParameters函数不存在):

内部数据(常量内部数据和最小值、常量内部数据和最大值){
静态标准::默认随机引擎生成器;
静态标准:均匀分布<int>分布(0,10);
分布。更改参数(最小值、最大值);
回流分配(发电机);
}

另一种选择是在均匀分布上设置一个大范围,然后在第一个示例中使用mod like。然而,我正在做统计工作,所以我希望数字来自尽可能无偏的分布(例如,如果使用的分布范围不是(max-min)的倍数,则分布将略有偏差)。这是一种选择,但我想再次避免

解决方案此解决方案来自@konrad [email protected] ransom和@mathk的答案。随机数生成器的种子设定是为了满足我的特殊需要。更常见的方法是使用时间(NULL)。如果你在同一秒钟内制造了许多线程,那么它们就会得到相同的种子。即使使用clock(),这也是一个问题,因此我们包含线程id。一个缺点-会泄漏内存-——每个线程一个生成器

#如果已定义(_MSC_VER)//Visual studio
#定义线程\u本地\u declspec(线程)
#elif defined(_GCC__)//GCC
#定义线程\u本地\u线程
#恩迪夫
#包括<随机>
#包括<时间;
#包括<螺纹>
使用名称空间std;
/*线程安全函数,返回最小值和最大值(包括最小值和最大值)之间的随机数。
此函数所需时间约为调用rand()所需时间的142%。额外的费用
您可以获得更好的均匀分布和线程安全性*/
内部传输(常量内部和最小值、常量内部和最大值){
静态线程_local mt19937*生成器=nullptr;
如果(!generator)generator=new mt19937(clock()+this_thread::get_id().hash());
均匀整数分布<整数>分布(最小值、最大值);
返回分配(*发电机);
}

你试过这个吗

内部数据(常量内部数据和最小值、常量内部数据和最大值){
静态线程_本地标准::mt19937发生器;
标准:均匀分布(最小值、最大值);
回流分配(发电机);
}

分布非常便宜(它们将完全由优化程序内联,因此唯一剩余的开销是实际的随机数重缩放)。不要害怕根据需要频繁地重新生成它们——事实上,从概念上讲,重置它们并不便宜(这就是为什么不存在该操作的原因)

另一方面,实际的随机数生成器是一个沉重的对象,承载大量状态,需要相当长的时间来构造,因此每个线程只能初始化一次(或者甚至跨线程初始化一次,但从长远来看,您需要同步访问,这会更昂贵)

发表评论