現在、疑似乱数を生成するためのシードを必要とするFortranのメインアプリケーションがあります。完全に無相関のシード(さらに完全に独立した疑似乱数チェーン)を使用して、このアプリケーションを何度も(何度も)実行したいと思います。
私の質問は:C ++ 2011でシードを生成する方法は?
/dev/urandom
メインスレッドで、適切なランダムソース( Linuxなど)から単一のシード(またはシードシーケンス)を抽出します。そのデータを使用して、単一のルートPRNGをシードします。次に、そのPRNGを使用して、スレッドローカルPRNGのシード値を生成します。
#include <random>
#include <vector>
typedef std::mt19937 rng_type;
std::uniform_int_distribution<rng_type::result_type> udist;
int main()
{
rng_type rng;
// seed rng first, and store the result in a log file:
rng_type::result_type const root_seed = get_seed();
rng.seed(root_seed);
// make thread seeds:
std::vector<rng_type::result_type> seeds(NUMBER_OF_THREADS);
for (auto & n : seeds) { n = udist(rng); }
// make threads...
}
の乱数エンジンインターフェイスを使用すると、単一の整数と整数のシーケンス<random>
の両方からシードできます。追加のランダム性が必要な場合は、数百の整数のシーケンスからをシードできます。mt19937
C ++ 11はstd::random_device
、ソースが利用可能な場合に非決定論的な乱数を提供します。ただし、実装をチェックして、それが適切であることを確認する必要があります。libc++はデフォルトで/dev/urandomを使用します。_GLIBCXX_USE_RANDOM_TR1
マクロが定義されている場合、libstdc++も同様に機能します。Visual Studioの実装は、残念ながら非決定論的ではありません。編集:VS2012の時点で、それらの実装はWindowsの暗号化サービスを使用しています。
ランダム性の非決定論的ソースへのアクセスを提供する場合std::random_device
(通常、/ dev / urandomは暗号化PRNGを使用します)、これは独立したシードを生成するのに十分なはずです。
#include <random>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 engine(seed);
}
単一の値をシードとして使用する代わりに、一部のエンジンはより多くのシードデータでより適切に機能する場合があります。シードシーケンスは、標準で提供される代替手段です。エンジンにはシードシーケンスをシードできます。シードシーケンスは、任意の量のデータをロードするオブジェクトであり、それに基づいてシードデータを生成します。
std::random_device r;
std::vector<std::mt19937> engines;
int engines = 50;
for (int i = 0; i < engines; ++i) {
std::seed_seq s{r(), r(), r(), r(), r(), r(), r(), r()};
engines.emplace_back(s);
}
32ビット値は8つ、256ビットで十分ですが、本当に必要な場合はさらに使用できます。各標準エンジンは、シードシーケンスから使用するデータの量を文書化します。
たとえば、各mt19937エンジンはmt19937::state_size
、シードシーケンスから(624)32ビット値を取得します。シードシーケンスから取得されたシードは入力データと同じではありませんが、それらはそのデータに基づいているため、シーケンスでその多くのランダムデータを使用できます。
std::random_device r;
std::vector<std::uint_least32_t> data;
std::generate_n(back_inserter(data), 624, std::ref(r));
std::seed_seq seed(begin(data), end(data));
std::mt19937 engine(seed); // 'fully' seeded mt19937
ランダムシードを実際に生成することはできません。あなたはどこかからそれらを引っ張ります。/dev/urandom
OSには、シードに使用できる疑似乱数値(Linuxなど)を取得する方法がある可能性があります。
現在の時刻を表すタイムスタンプを取得することも一般的なオプションです。スレッドごとに異なるシードを取得するには、わずかに異なる時刻にタイムスタンプを要求するようにし、高解像度タイマーを使用して実際に取得するようにします。シードとしての異なる値。
このような関数は本質的に無意味であるため、C++11に組み込まれている「適切なシードを取得する」関数はありません。コンピューターはランダムデータを生成できません。目的に応じて十分にランダムに見えるものを選択し、それを使用してランダムジェネレーターをシードする必要があります