C#并行播种StaticRandom以获得可重现的序列

mda*_*mda 3 c# random multithreading seed

我正在研究一个在parallel.for循环中需要随机数的C#项目.为此,我使用Jon Skeet的MiscUtil中的StaticRandom类.

为了测试,我希望能够重现我的结果.因此,我尝试在每次测试运行时为底层System.Random播种以获得相同的序列.然而,即使种子我每次都得到不同的结果.在常规for循环中,每次输出相同的序列.下面有代码重现我的问题(您必须使用机器的输出更新预期的顺序).

有没有办法播种Random,所以我可以在parallel.for循环中获得可重现的序列?

    [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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 8

当您Parallel.For按设计使用时,您将不按顺序获得结果,因为每次迭代将以非确定性方式并行运行.如果您需要具有相同的"随机"数字序列,则需要以Random.Next()可靠的顺序调用.这不适用于多个线程.

Parallel.For您应该考虑提前生成"随机"数字序列,而不是尝试使用填充随机数,然后Parallel.For根据这些数字用于处理.这样,您将始终以正确的顺序生成数字,这将保留排序.