我剛開始玩任務並行庫,並遇到有趣的問題;我對正在發生的事情有一個總體概念,但希望聽到比我更能勝任的人的意見,幫助我們瞭解正在發生的事情。我對有點冗長的代碼表示歉意。並行循環和隨機產生奇數結果
我開始用的隨機遊走非並行模擬:
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