gpt4 book ai didi

random - 并行循环和随机产生奇怪的结果

转载 作者:行者123 更新时间:2023-12-04 08:30:14 24 4
gpt4 key购买 nike

我刚开始使用 Task Parallel Library,遇到了一些有趣的问题;我对正在发生的事情有一个大致的了解,但希望听到比我更有能力的人的评论,以帮助了解正在发生的事情。对于有点冗长的代码,我深表歉意。

我从随机游走的非平行模拟开始:

 var random = new Random();
Stopwatch stopwatch = new Stopwatch();

stopwatch.Start();

var simulations = new List<int>();
for (var run = 0; run < 20; run++)
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (random.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}

Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
simulations.Add(position);
}

Console.WriteLine(string.Format("Average position: {0} .", simulations.Average()));
stopwatch.Stop();

Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));
Console.ReadLine();

然后我写了我在并行循环中的第一次尝试:
 var localRandom = new Random();

stopwatch.Reset();
stopwatch.Start();

var parallelSimulations = new List<int>();
Parallel.For(0, 20, run =>
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (localRandom.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}

Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
parallelSimulations.Add(position);
});


Console.WriteLine(string.Format("Average position: {0} .", parallelSimulations.Average()));
stopwatch.Stop();

Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));

Console.ReadLine();

当我在设置为仅使用 1 个核心的虚拟机上运行它时,我观察到类似的持续时间,但不再按顺序处理运行 - 这并不奇怪。

当我在双核机器上运行它时,事情变得很奇怪。我没有看到任何改进,并且每次运行都观察到一些非常奇怪的结果。大多数运行的结果是 -1,000,000,(或非常接近),这表明 Random.Next 始终返回 0 quasi。

当我为每个循环设置随机本地时,一切正常,并且我得到了预期的持续时间改进:
Parallel.For(0, 20, run =>
{
var localRandom = new Random();
var position = 0;

我的猜测是,问题与 Random 对象在循环之间共享并具有某种状态这一事实有关。 “并行失败”版本的持续时间缺乏改进是因为我认为对 Random 的调用不是并行处理的(即使我看到并行版本使用两个内核,而原始版本没有) .我真正不明白的是为什么模拟结果是这样的。

我有一个单独的担忧是,如果我使用每个循环本地的 Random 实例,我可能会遇到以相同种子开始的多个循环的问题(当您生成多个 Random 的时间太近时会遇到的问题,导致相同的序列)。

任何对正在发生的事情的见解对我来说都是非常有值(value)的!

最佳答案

Random类不是线程安全的;如果你在多个线程上使用它,它可能会变得一团糟。

您应该单独制作 Random每个线程上的实例,并确保它们最终不会使用相同的种子。 (例如, Environment.TickCount * Thread.CurrentThread.ManagedThreadId )

关于random - 并行循环和随机产生奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2924599/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com