8

次のクラスを実装しようとしています。

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()メンバー関数があります。つまり、潜在的に大きな内部状態またはキャッシュがある可能性があります。

私の質問は:

  1. ディストリビューションには内部状態がありますか? はいの場合、なぜですか?標準は、この状態のサイズについて何か言っていますか?

  2. 私のように実装するのは良い考えですか?より良い方法はありますか?

4

4 に答える 4

2

RandomNumberDistribution テンプレート ポリシーのドキュメントを参照してください...

reset():

配布オブジェクトの内部状態をリセットします。この関数の呼び出し後、ディストリビューション オブジェクトでの operator() の次の呼び出しは、以前の operator() の呼び出しに依存しません。

これは、 へoperator()の呼び出しが、後続の への呼び出しに影響する状態を変更できることを意味しますoperator()。それが存在する理由であり、reset()存在しoperator()ない理由でもありconstます。

uniform_real_distributionあなたが言ったように、小さな単純な関手でなければなりません。構築に使用した 2 のみを保持するだけRealで、他には何も保持しない可能性があります。そしてreset()、その人のために何もするべきではありません。

于 2013-04-15T14:35:02.587 に答える
2

はい、ディストリビューションは内部状態を持つことができます。通常は小さいですが、サイズが気になる場合は確認してください。

于 2013-04-15T14:51:38.110 に答える
2

状態の仕様reset():

その後の d の使用は、リセットを呼び出す前にエンジンによって生成された値に依存しません。

これは、通常、 の呼び出しがoperator()、 の前の呼び出しで使用されたエンジンによって生成された値に依存する可能性があることを意味しますoperator()。つまり、ディストリビューションはキャッシュするか、以前のエンジンの結果に依存することができます。

たとえば、特定のエンジンが一度に 32 ビットを提供する一方で、ベルヌーイ分布は結果を生成するために 1 ビットしか必要としない場合があります。そのため、分布は 32 ビットをキャッシュし、32 個の値が生成されるまでエンジンを再度呼び出すことはありません。

もう 1 つの例は、一般的なアルゴリズムが自然に一度に 2 つの値を生成する分布 (どれかは忘れました) です。したがって、分布は次の呼び出しのために 2 番目の値を保存する可能性があります。

そうです、ディストリビューションは内部状態を持つことができます。標準では、この状態のサイズに要件を課していません。

スレッド間でディストリビューションを共有してもよいかどうかを尋ねている場合、いいえ、それは良い考えではありません。これを行うことの 1 つはデータ競合であり、同期を追加するか、配布を const にしない限り、未定義の動作が発生します (標準ライブラリの実装でそれを行うことができたとしても、移植性はありません)。第二に、標準はディストリビューションとエンジンを特定の方法で使用する場合にのみ保証を行い、複数のエンジン間でディストリビューションを共有することはその方法ではありません。ディストリビューションを共有することで実際に悪いデータが生成される可能性は低いですが、IMO ではそうしないことをお勧めします。代わりに、各スレッドに独自のエンジンと独自のディストリビューションの両方を保持させることができます。

于 2013-04-15T15:48:04.383 に答える