我刚开始玩任务并行库,遇到了一些有趣的问题;我对正在发生的事情有一个大致的了解,但想听听比我更有能力的人的评论,以帮助了解正在发生的事情。对于有点冗长的代码,我深表歉意。
我从随机游走的非并行模拟开始:
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 准。
当我对每个循环进行随机本地化时,一切正常,并且我得到了预期的持续时间改进:
Parallel.For(0, 20, run =>
{
var localRandom = new Random();
var position = 0;
我的猜测是,问题与 Random 对象在循环之间共享并具有某种状态的事实有关。我认为“并行失败”版本的持续时间缺乏改进是因为对 Random 的调用没有并行处理(即使我看到并行版本使用两个内核,而原始版本没有) . 我真的不明白为什么模拟结果是这样的。
我有一个单独的担忧是,如果我在每个循环本地使用 Random 实例,我可能会遇到多个循环从同一个种子开始的问题(当你生成多个 Random 的时间太接近时会出现问题,导致相同的序列)。
对正在发生的事情的任何见解对我来说都是非常有价值的!