3

私は、parallel.for ループで乱数を必要とする C# プロジェクトに取り組んでいます。この目的のために、Jon Skeet の MiscUtil の StaticRandom クラスを使用しています。

テストのために、結果を再現できるようにしたいと考えています。したがって、テストが実行されるたびに同じシーケンスを取得するために、基になる System.Random をシードしようとしました。ただし、シードを使用しても、毎回異なる結果が得られます。通常の for ループでは、毎回同じシーケンスが出力されます。以下に私の問題を再現するコードがあります(マシンからの出力で予想されるシーケンスを更新する必要があります)。

parallel.for ループで再現可能なシーケンスを取得できるように、Random をシードする方法はありますか?

    [TestMethod]
    public void MultiThreadedSeededRandom()
    {
        var actual = new ConcurrentBag<int>();
        Parallel.For(0, 10, i =>
        {
            actual.Add(StaticRandom.Next(1000));
        });

        WriteActualToOutput(actual);

        var expected = new int[] { 743, 51, 847, 682, 368, 959, 245, 849, 192, 440, };

        Assert.IsTrue(AreEqual(expected, actual.ToArray()));
    }

    public static bool AreEqual<T>(T[] expected, T[] actual)
    {
        if (expected.Length != actual.Length)
            return false;

        for (int i = 0; i < expected.Length; i++)
        {
            if (!expected[i].Equals(actual[i]))
                return false;
        }
        return true;
    }

    private static void WriteActualToOutput(ConcurrentBag<int> acual)
    {
        var result = string.Empty;
        result += "new int[] {";
        foreach (var value in acual)
        {
            result += value.ToString() + ",";
        }
        result += "};";

        Trace.WriteLine(result);
    }

    public static class StaticRandom
    {
        private static Random random = new Random(1231241);
        private static object myLock = new object();

        public static int Next(int max)
        {
            object obj;
            Monitor.Enter(obj = StaticRandom.myLock);
            int result;
            try
            {
                result = StaticRandom.random.Next(max);
            }
            finally
            {
                Monitor.Exit(obj);
            }
            return result;
        }
    }
4

2 に答える 2

8

を使用するParallel.Forと、設計上、各反復が非決定論的な方法で並行して実行されるため、結果が順不同になります。「乱数」の同じシーケンスが必要な場合はRandom.Next()、信頼できる順序で呼び出す必要があります。これは、複数のスレッドからは機能しません。

を使用して乱数を入力しようとする代わりにParallel.For、事前に一連の「乱数」を生成し、Parallel.For後でこれらの数値に基づいて を使用して処理を行うことを検討する必要があります。このようにして、常に適切な順序で番号を生成し、順序付けを維持します。

于 2013-03-04T19:15:20.730 に答える