[英]Is mersenne twister thread safe for cpp
#include <random>
int f() {
std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
}
多個線程可以安全地調用此函數嗎? 功能線程安全嗎? 調用std::random_device seeder;
是有意義的std::random_device seeder;
和std::mt19937 engine(seeder());
每次?
No C ++ std
類型以非線程安全的方式使用全局數據。 可以在不同的線程中訪問這種類型的兩個不相關的實例。
默認情況下,如果沒有同步,則無法從兩個線程訪問一個類型的實例。
您是創建的局部變量。 這些局部變量與其類型的任何其他實例無關。 這里沒有線程安全問題。
通過具有狀態並重用它來最有效地產生偽隨機值。 你沒有這樣做,所以從1到6的隨機數創建起來相對昂貴。
std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
您對std::mt19937
是多余的。 您已經創建了一個random_device
,可以直接將其提供給dist
,然后從中創建engine
,然后使用engine
。 在這里使用engine
是沒用的。
Traditionaly您創建一個engine
(某種類型的,像mt19937
從) 一次 seeder
。 然后存儲engine
,並重復將其傳遞給分發。
這通過相對昂貴的“實際隨機數”生成一次,以通過分布引擎生成一系列長的偽隨機數。
但是請注意,這種使用有成本; 您必須存儲engine
並且必須防止多線程訪問它。
執行此操作的“正確”方法是讓對象為您生成隨機值,並將其傳遞到您需要的位置。 存儲使用的初始種子也允許您重復執行所涉及的隨機數集。
如果你不喜歡明確傳遞隨機狀態的想法,你可以使用thread_local
(或帶有mutex
static
)。
thread_local std::mt19937 engine(std::random_device{}());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
這會為每個線程創建一個engine
,並使用random_device
的值初始化engine
。
多個線程可以安全地調用此函數嗎? 功能線程安全嗎?
此特定功能是線程安全的。 可以創建隨機數生成器,引擎和分發,並在多個線程中調用在函數本地引擎中生成數字。
當然,由於cout
不同步,因此可以交錯來自多個線程的輸出。
我是否需要在每個函數調用中初始化引擎
這就是你的功能所做的,雖然這確保了線程安全,但它與你需要做的事情相反。 每次初始化引擎將使“隨機性”序列直接取決於播種機。 它當然會增加初始化引擎的開銷。
或者將前兩行(播種機和引擎)放在類構造函數中會更好嗎?
您可以使用包裝類,但不必使用。 這與您是否在每個函數調用中創建新引擎實例是正交的。 只要每個函數調用使用與先前調用相同的引擎,在這方面就沒有隨機性問題。
但是跨線程使用相同的引擎確實不是線程安全的。 您可以在每個線程中使用一個引擎 - 或使用互斥鎖保護共享引擎,但這會產生很大的開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.