[英]What is a C++11 random distribution made of?
我正在嘗試實現以下類:
typedef std::mt19937 Engine;
class Interval
{
public:
double upperBoundary;
double lowerBoundary;
double generateUniformRandomNumber(Engine& engine);
};
我希望這個類在多線程環境中工作。 每個線程都有自己的Engine
對象實例,它會將Engine
傳遞給任何具有隨機行為的類的對象。
為了均勻地產生隨機數的C ++ 11的方式,在實施generateUniformRandomNumber
必須是這樣的:
uniform_real_distribution<double> distribution_; // private member of Interval
double Interval::generateUniformRandomNumber(Engine& engine)
{
return distribution_(engine);
}
問題是我不理解C ++ 11發行版。 我知道C ++ 11隨機數引擎可以是非常大的對象(幾千字節),但是分布呢? 起初我認為發行版只是簡單的仿函數,其中operator()
是一個pure const
函數,但它似乎既不pure
也不是const
。 根據該引用 ,每個分發實例都有一個reset()
成員函數。 這意味着它有一個潛在的大內部狀態或緩存。
我的問題是:
分配是否具有內部狀態? 如果是,為什么? 標准是否說明了這個州的規模?
像我一樣做一個實現是一個好主意嗎? 有沒有更好的辦法?
分布可能很好,通常會有一些狀態。 該標准在此不作任何限制。 我可以想到可以使用狀態的幾個原因:
隨機數分布通常具有一些參數來配置它。 例如,正態分布具有均值和方差參數。 這些都是其州的一部分,因為它們必須保持在調用之間。
分發是根據其他一些分發實現的。 你真的可以把它想象成一個更復雜的參數。 例如,我的beta發布實現保留了兩個gamma發行版,每個發行版都有自己的配置。
分布可能會隨着時間而改變。 沒有什么可說的,分發的重復調用需要是獨立的。 這是reset
成員函數的用武之地。大多數發行版都有對operator()
獨立調用,因此reset
函數實際上什么都不做(它的定義是空的)。 但是,如果您的呼叫是相關的,則reset
應使分發回到下一個呼叫獨立的狀態。
你的實現似乎很好。 uniform_real_distribution<double>
不太可能具有您構造它的參數的更多狀態。
查看RandomNumberDistribution模板策略的文檔...
reset()
:
重置分發對象的內部狀態。 調用此函數后,對分發對象的下一次operator()調用將不依賴於之前對operator()的調用。
這意味着對operator()
調用可以改變影響后續調用operator()
。 這就是為什么reset()
存在以及為什么operator()
不是const
。
uniform_real_distribution
應該是一個簡單的小函子,就像你說的那樣。 它可能只是擁有它所構建的2 Real
,而沒有別的。 而reset()
應該對那個什么都不做。
是的,分發可以有內部狀態。 它們通常很小,但如果您擔心尺寸,請檢查它。
reset()
的規范說明:
d的后續使用不依賴於任何引擎在調用reset之前產生的值。
這意味着通常對operator()
調用可能取決於先前調用operator()
使用的引擎所產生的值。 也就是說,分發可以緩存或以其他方式依賴於先前的引擎結果。
例如,伯努利分布可能只需要一位來產生結果,而給定引擎一次提供32位,因此分布可能會緩存32位而不會再次調用任何引擎,直到生成了32個值。
另一個例子是分布(我忘了哪個),其中公共算法一次自然地產生兩個值,因此分布可以為下一個調用保存第二個值。
所以是的,分布可以有內部狀態。 該標准不對此狀態的大小提出要求。
如果你問是否可以在線程之間共享分配,那么不,這不是一個好主意。 這樣做的一件事是數據爭用並導致未定義的行為,除非您添加同步或使分布const(即使您可以使用標准庫的實現,這是不可移植的)。 其次,標准只有在以特定方式使用分布和引擎並且在多個引擎之間共享分配時才能提供保證。 共享分發實際上不太可能產生不良數據,但是IMO仍然不應該這樣做。 相反,您可能讓每個線程都保留自己的引擎和自己的分發。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.