問題描述
我的程序需要在某個范圍內(nèi)生成許多隨機(jī)整數(shù)(int min,int max).每次調(diào)用都有一個不同的范圍.什么是好的(最好是線程安全的)方法來做到這一點?以下不是線程安全的(并且使用了人們似乎不鼓勵的 rand()):
My program needs to generate many random integers in some range (int min, int max). Each call will have a different range. What is a good (preferably thread-safe) way to do this? The following is not thread-safe (and uses rand(), which people seem to discourage):
int intRand(const int & min, const int & max)
{
return (rand() % (max+1-min)) + min;
}
這慢很多,但使用
:
int intRand(const int & min, const int & max) {
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(min,max);
return distribution(generator);
}
這樣的事情就是我想要的(雖然 changeParameters 函數(shù)不存在):
Something like this is what I'm going for (the changeParameters function doesn't exist though):
int intRand(const int & min, const int & max) {
static std::default_random_engine generator;
static std::uniform_int_distribution<int> distribution(0, 10);
distribution.changeParameters(min, max);
return distribution(generator);
}
另一種選擇是在 uniform_int_distribution
上做一個廣泛的范圍,然后像第一個例子一樣使用 mod.但是,我正在做統(tǒng)計工作,所以我希望數(shù)字來自盡可能無偏的分布(例如,如果使用的分布范圍不是 (max-min) 的倍數(shù),分布將略微有偏見).這是一個選項,但同樣,我想避免它.
Another option would be to make a wide range on the uniform_int_distribution
and then use mod like in the first example. However, I'm doing statistical work, so I want the numbers to come from as unbiased of a distribution as possible (e.g., if the range of the distribution used is not a multiple of (max-min), the distribution will be slightly biased). This is an option, but again, I would like to avoid it.
解決方案 此解決方案來自 @konrad-rudolph @mark-ransom 和 @mathk 的答案.隨機(jī)數(shù)生成器的播種是為了滿足我的特定需求.更常見的方法是使用 time(NULL).如果您在同一秒內(nèi)創(chuàng)建多個線程,那么它們將獲得相同的種子.即使使用 clock() 這也是一個問題,所以我們包含線程 id.一個缺點 - 這會泄漏內(nèi)存 --- 每個線程一個生成器.
SOLUTION This solution comes from the answers by @konrad-rudolph @mark-ransom and @mathk . The seeding of the random number generator is done to suit my particular needs. A more common approach would be to use time(NULL). If you make many threads in the same second, they would then get the same seed though. Even with clock() this is an issue, so we include the thread id. A drawback - this leaks memory --- one generator per thread.
#if defined (_MSC_VER) // Visual studio
#define thread_local __declspec( thread )
#elif defined (__GCC__) // GCC
#define thread_local __thread
#endif
#include <random>
#include <time.h>
#include <thread>
using namespace std;
/* Thread-safe function that returns a random number between min and max (inclusive).
This function takes ~142% the time that calling rand() would take. For this extra
cost you get a better uniform distribution and thread-safety. */
int intRand(const int & min, const int & max) {
static thread_local mt19937* generator = nullptr;
if (!generator) generator = new mt19937(clock() + this_thread::get_id().hash());
uniform_int_distribution<int> distribution(min, max);
return distribution(*generator);
}
推薦答案
你試過了嗎?
int intRand(const int & min, const int & max) {
static thread_local std::mt19937 generator;
std::uniform_int_distribution<int> distribution(min,max);
return distribution(generator);
}
分布非常便宜(它們將被優(yōu)化器完全內(nèi)聯(lián),因此唯一剩余的開銷是實際的隨機(jī)數(shù)重新縮放).不要害怕根據(jù)需要經(jīng)常重新生成它們 - 事實上,從概念上講,重置它們并不便宜(這就是為什么不存在該操作的原因).
Distributions are extremely cheap (they will be completely inlined by the optimiser so that the only remaining overhead is the actual random number rescaling). Don’t be afraid to regenerate them as often as you need –?in fact, resetting them would conceptually be no cheaper (which is why that operation doesn’t exist).
另一方面,實際的隨機(jī)數(shù)生成器是一個重量級的對象,帶有很多狀態(tài)并且需要相當(dāng)長的時間來構(gòu)建,因此每個線程(甚至跨線程,但那么你就需要同步訪問,從長遠(yuǎn)來看這會更昂貴).
The actual random number generator, on the other hand, is a heavy-weight object carrying a lot of state and requiring quite some time to be constructed, so that should only be initialised once per thread (or even across threads, but then you’d need to synchronise access which is more costly in the long run).
這篇關(guān)于如何生成線程安全的統(tǒng)一隨機(jī)數(shù)?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!