Подтвердить что ты не робот

Почему Parallel.ForEach не запускает несколько потоков?

Сегодня я попытался сделать некоторую оптимизацию для оператора foreach, который работает на XDocument.

Перед оптимизацией:

foreach (XElement elem in xDoc.Descendants("APSEvent").ToList())
{
    //some operations
}

После оптимизации:

Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), elem =>
{
    //same operations
});

Я увидел, что .NET в Parallel.ForEach(...) открыт ТОЛЬКО один поток! В результате временной интервал Parallel был больше стандартного foreach.

Почему вы думаете, что .NET только открыл 1 поток? Из-за блокировки файла? Благодаря

4b9b3361

Ответ 1

По дизайну Parallel.ForEach может использовать меньшее количество потоков, чем требуется для достижения более высокой производительности. Согласно MSDN [link]:

По умолчанию методы Parallel.ForEach и Parallel.For могут использовать переменное количество задач. Вот почему, например, класс ParallelOptions обладает свойством MaxDegreeOfParallelism вместо свойства MinDegreeOfParallelism. Идея состоит в том, что система может использовать меньше потоков, чем запросить обработку цикла.

Пул потоков .NET динамически адаптируется к изменяющимся рабочим нагрузкам, позволяя с течением времени изменять количество рабочих потоков для параллельных задач. Во время выполнения система наблюдает, увеличивается ли увеличение количества потоков или ухудшает общую пропускную способность и соответственно корректирует количество рабочих потоков.

Ответ 2

используйте его следующим образом:

int ParallelThreads = 10;
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), new ParallelOptions() { MaxDegreeOfParallelism = ParallelThreads }, (myXDOC, i, j) =>
{
 //do whatever you want here 
});

Ответ 3

Из описания проблемы ничего не объясняется, почему TPL не порождает больше потоков.

В вопросе нет никаких доказательств, что даже проблема. Это можно устранить довольно легко: вы можете записать идентификатор потока, прежде чем вводить цикл, и как первая вещь, которую вы делаете внутри своего цикла.

Если это всегда одно и то же число, то TPL не сможет генерировать потоки. Затем вы должны попробовать разные версии вашего кода и какое изменение запускает TPL для сериализации всего. Одна из причин может быть, если в вашем списке небольшое количество элементов. TPL разделяет вашу коллекцию, и если у вас есть только несколько элементов, вы можете получить только одну партию. Это поведение настраивается, кстати.

Возможно, вы случайно включили блокировку в цикле, тогда вы увидите множество разных чисел, но не ускорьтесь. Затем упростите код, пока проблема не исчезнет.

Ответ 5

Да точно, Document.Load(...) блокирует файл и из-за конфликта ресурсов между потоками, TPL не может использовать мощность нескольких потоков. Попробуйте загрузить XML в Stream, а затем используйте Parallel.For(...).

Ответ 6

Есть ли у вас один процессор? В этом случае TPL может ограничить количество потоков. То же самое может произойти, если коллекция очень мала. Попробуйте большую коллекцию. Подробнее о том, как определяется степень parallelism, см. этот ответ.