簡體   English   中英

mersenne twister線程對cpp是否安全

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM