2016-09-02 10 views
8

私はC++ 11ランダムライブラリについて少し混乱しています。私が理解なぜrandom_deviceを使用しないのですか?

  • ランダムエンジン(擬似(シードが必要)、または実際とすることができる)
  • 分布:それは、特定のエンジンから取得した番号をマッピングし、我々は二つの別々の概念を必要とします間隔、特定の分布を使用します。

    std::random_device rd; 
    std::uniform_int_distribution<int> dist(1, 5); 
    
    // get random numbers with: 
    dist(rd); 
    

    を私の知る限り、これがうまく機能言うことができるように:私は理解していない何

はこれを使用しない理由です。

代わりに、これは私がほとんどの例/サイト/記事で見つけたものです:私は、例えば、特殊な用途の話ではないのです

std::random_device rd; 
std::mt19937 e{rd()}; // or std::default_random_engine e{rd()}; 
std::uniform_int_distribution<int> dist{1, 5}; 

// get random numbers with: 
dist(e); 

暗号化、あなたの基本的な始めの記事。

std::mt19937(またはstd::default_random_engine)はシードを受け入れるため、デバッグセッション中に同じシードを指定するとデバッグが容易になります。

はまた、なぜだけではない:

std::mt19937 e{std::random_device{}()}; 
+7

_ "多くの実装のrandom_deviceのパフォーマンスは、エントロピープールが使い果たされると急激に低下します。実用的には、random_deviceは一般にmt19937" _ [source](http://en.cppreference。 – Michael

+1

@Michael答えがあるはずです –

+0

答えはより詳細に(たとえば、パフォーマンスが低下するなど)必要になるかもしれません。それで、なぜ私はコメントとして投稿したのですか? – Michael

答えて

8

また、なぜだけでなく:

std::mt19937 e{std::random_device{}()};

あなたは一度だけこれを行います場合は罰金かもしれませんが、あなたはそれを何度も行います場合、それはですあなたのstd::random_deviceを追跡し、それを不必要に作成/破壊しないほうが良い。

std::random_deviceの実装については、libC++のソースコードを参照すると役に立ちます。これは非常に簡単です。それはstd::fopen("/dev/urandom")以上の薄いラッパーです。したがって、std::random_deviceを作成するたびに、別のファイルシステムハンドルが取得され、関連するすべてのコストが発生します。

私が理解しているように、std::random_deviceは、マイクロソフト暗号APIの呼び出しを表しているため、これを行うたびに一部の暗号ライブラリインターフェイスを初期化して破棄します。

これはアプリケーションによって異なりますが、一般的な目的のためにはこのオーバーヘッドを常に無視できるとは思いません。時には、それは素晴らしいです。

私は戻ってあなたの最初の質問にこの関係を推測する:私が思う

std::random_device rd; 
std::mt19937 e{rd()}; // or std::default_random_engine e{rd()}; 
std::uniform_int_distribution<int> dist{1, 5}; 

少なくとも方法:代わりに、これは私がほとんどの例/サイト/記事で見つけたものです

約:

  • std::mt19937は非常にシンプルで信頼性が高いルランダムジェネレータ。実装はであり、標準ではであり、少なくともブーストでは、元のmt19937紙に由来するすべての場所で同じコードを使用していました。このコードは非常に安定しており、クロスプラットフォームです。初期化やそれからのクエリなどは、コンパイルしたプラットフォーム上で同様のコードにコンパイルし、同様のパフォーマンスを得ることができると確信できます。対照的に、かなり不透明です。

  • std::random_deviceあなたはそれが何であるか、それが何をしようとしているのか、それがいかに効率的であるかを本当に分かりません。実際に取得できるかどうかも分かりません。作成しようとすると例外がスローされる可能性があります。あなたはそれが種を必要としないことを知っています。あなたは通常、そこから数多くのデータを取り出し、シードを生成するために使用するだけではありません。時には、暗号APIとの素晴らしいインターフェースとして機能することもありますが、それを実際に行う必要はありません。悲しいことに、時にはそうでない場合もあります。 UNIXでは/dev/randomに対応している可能性があります。/dev/urandom/に対応している可能性があります。 MSVC暗号API(ビジュアルスタジオ)に対応している場合もあれば、固定定数(mingw)の場合もあります。いくつかの電話機でクロスコンパイルすれば、それが何をするのか分かります。 (また、/dev/randomを取得しても、パフォーマンスはと一致しないことがあります。 - エントロピープールが使い果たされてから犬として遅くなるまでは、うまくいくように見えます。)

私はそれについて考える方法は、std::random_devicetime(NULL)と播種の改良版のようなことになっているされて - time(NULL)はかなり安っぽい種と考えられ、すべてのものですので、それは、低いバーです。私は通常、その日に戻って種を生成するためにtime(NULL)を使ったでしょう。私はそれ以外のものをそれほど有用とは考えていません。

6

This articleは起動に良い点です。

私はいくつかのポイントを合成するつもりです:

  • それが不明なコストがかかります。

    この「デバイス」から数値を読み取るのにどれくらいの費用がかかりますか?それは不特定です。例えば、Linuxシステムで/ dev/randomから読み込むことができます。これは、エントロピーを待つ長い期間ブロックすることができます(これは、さまざまな理由で問題があります)。私の個人的な経験のために

私はstd::random_deviceは、単純な疑似randomicアルゴリズムよりも通常遅いことを通知しました。それは一般的には真実ではないかもしれませんが、通常はそうです。なぜなら、物理的なデバイスや、単純なCPU以外のハードウェアを必要とするからです。

  • 実際に決定的である可能性があります。

    C++ 11のstd :: random_deviceは非決定的である必要はありません!実装では、シードが固定された単純なRNGとして実装することができます。そのため、プログラムの実行ごとに同じ出力が生成されます。

関連する問題