Parallel.ForEach
будет использовать столько потоков, сколько планировщик предоставляет по умолчанию ( ссылка ). Имейте в виду, что в документации указано:
Выполняет операцию foreach (For Each в Visual Basi c) на Partitioner, в которой итерации могут выполняться параллельно, а параметры l oop могут быть настроены.
Так что, возможно, это просто не подходит для параметров по умолчанию.
После запуска вашего кода я обнаружил следующее (при нажатии на параллельную часть):
As you can see it already utilized 15Gb of memory but it's running on all cores. I'm quite sure you run into memory/GC bottlenecks rather than CPU bottlenecks.
I run some additional performance analysis. This is what I found (String::Concat
can be ignored because it's part of the initialization):
Line 45 is taking up ~50% of the CPU time.
введите описание изображения здесь
Я немного поигрался с кодом и внес следующие изменения:
Parallel.ForEach(
source,
() => new List<string[]>(),
(line, loop, local) =>
{
var length = line.Length;
var processedLine = new string[length];
for (var i = 0; i < length; ++i)
{
processedLine[i] = line[i].Reverse() + "";
}
local.Add(processedLine);
return local;
},
partitionResult =>
{
lock (processed)
{
processed.AddRange(partitionResult);
}
});
С удвоенным размером данных (10000000
~ 32 ГБ данных) это показывает как минимум небольшой пик использования ЦП, но он выполняется менее чем за 7 секунд , поэтому я не совсем уверен, что TaskManager действительно правильно получает пик. Тем не менее, это также не решает проблему, и G C также работает как сумасшедший.
Моим «окончательным» выводом было бы то, что это либо (или несколько):
что вас сдерживает.
На мой взгляд, это приятно пример того, почему распараллеливание не даст в x -кратное увеличение производительности, даже если вы можете использовать x -потоки.