5

私はAIコンテストのホストをやっていて、ランダムな可能な値を選択するrandomBotを持っています。

ボットには、Init(_seed) と MakeMove() の 2 つのエクスポート関数があります。

まったく同じゲームをプレイするには、ホストが各ボットに対して定義されたシード値を持っています。Init 関数でそれを渡します。

random bot の Init 関数には srand(_seed) 関数呼び出しがあります。ランダムボットの MakeMove 関数には、rand() 関数呼び出しがあります。

ここでの問題は、2 つのボットをロードした後、各ゲームは同じシード値で同じになるはずですが、それらは異なるということです。

私が知っているように、srand はモジュール/スレッドごとに値を保存し、共有しないでください。

テストを行い、それぞれ srand と rand の呼び出しでエクスポートされない関数 mysrand と myrand を作成しました。

エクスポートされた関数内の srand と rand を mysrand と myrand に置き換えました...そしてうまくいきました...

なぜこうなったのかは分かっているのですが、よくわかりません...

なぜ正確にそれが起こるのか、それを回避する方法は、競技者にエクスポートされた関数内で必要な関数を使用してもらいたいからです (プロキシ関数を使用したくない)。

ありがとう。

Windows、コンパイラを使用しています: gcc、ビジュアル C++、ボーランド C++ ビルダー

4

3 に答える 3

5

一貫した動作を得たい場合<random>は、おそらくライブラリの方が適しています。RNG の状態を格納する場所を制御でき、エンジンは実装間で同じ値を生成できます (ただし、実装間で同じ出力を生成するために標準のディストリビューションは必要ありません)。

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] {
        // A simple example distribution function; not intended for real use.
        return static_cast<int>(eng()/static_cast<double>(eng.max() + 1ull) * 20.0) + 1;
    });
}

これにより、すべての実装で次のように出力されます。

17 3 19 17 3 20 19 5 13 7

実装全体ではなく、実装内で一貫した動作のみが必要な場合は、標準のディストリビューションを使用でき、RNG の状態がどこにあるかを引き続き制御できます。

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::uniform_int_distribution<> dist(1,20);
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] { return dist(eng); });
}

独自のディストリビューションを作成するよりも、標準のディストリビューションを優先する必要があります。

于 2012-06-10T06:21:59.210 に答える
2

私が知っているように、srandはモジュール/スレッドごとにその値を保存し、共有しないようにする必要があります。

これは必ずしも真実ではありません。randUbuntuのmanページから:

 The function rand() is not reentrant or thread-safe, since it uses hid‐
   den state that is modified on each call.  This might just be  the  seed
   value to be used by the next call, or it might be something more elabo‐
   rate.  In order to get reproducible behavior in a threaded application,
   this  state must be made explicit; this can be done using the reentrant
   function rand_r().

Cライブラリの実装がの共有状態ではなくローカル状態を明示的に使用していない場合、RNG状態が破損する可能性がありますrand

于 2012-06-10T04:31:13.033 に答える
1

各 dll を CRT に静的にリンクできます。これにより、各 dll に独自の rand 状態が与えられます。

于 2012-06-10T04:48:22.330 に答える