我刚开始玩任务并行库,并遇到有趣的问题;我对正在发生的事情有一个总体概念,但希望听到比我更能胜任的人的意见,帮助我们了解正在发生的事情。我对有点冗长的代码表示歉意。并行循环和随机产生奇数结果
我开始用的随机游走非并行模拟:
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的调用不是并行处理的(即使我看到并行版本使用两个核心,而原始版本不是) 。我真的没有得到的是为什么模拟结果是他们是。
我有一个单独的担心是,如果我在每个循环中使用本地随机实例,我可能会遇到多个循环以相同种子开始的问题(当您生成多个兰姆时太紧密,导致相同的序列)。
对发生的事情的任何洞察对我来说都是非常宝贵的!
Ade,感谢您指向S. Toub文章的指针,它非常棒。 – Mathias 2010-06-25 05:29:34