Я только начал играть с библиотекой параллельных задач и столкнулся с интересными проблемами; У меня есть общее представление о том, что происходит, но я хотел бы услышать комментарии от людей, более компетентных, чем я, чтобы помочь понять, что происходит. Мои извинения за довольно длинный код.
Я начал с непараллельного моделирования случайного блуждания:
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, локальные для каждого цикла, я могу столкнуться с проблемой наличия нескольких циклов, начинающихся с одного и того же начального числа (проблема, возникающая при создании нескольких рандомов слишком близко по времени в результате идентичные последовательности).
Любое понимание происходящего будет для меня очень ценным!