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

Что делает MaxDegreeOfParallelism?

Я использую Parallel.ForEach, и я делаю некоторые обновления баз данных, теперь без установки MaxDegreeOfParallelism, двухъядерный процессорный компьютер приводит к тайм-аутам в sql-клиентах, где, кроме того, процессор с четырьмя ядрами как-то не отключается.

Теперь у меня нет контроля над тем, какие ядра процессора доступны, где мой код работает, но есть ли какие-то настройки, которые я могу изменить с помощью MaxDegreeOfParallelism, который, вероятно, будет работать меньше операций одновременно и не приведет к таймаутам?

Я могу увеличить время ожидания, но это нехорошее решение, если на более низком процессоре я могу обрабатывать меньше операций одновременно, что уменьшит нагрузку на процессор.

Хорошо. Я также прочитал все другие сообщения и MSDN, но установлю MaxDegreeOfParallelism на меньшее значение, чтобы пострадали мои четырехъядерные процессоры?

Например, есть ли вообще что-то вроде: если у процессора есть два ядра, тогда используйте 20, если у процессора четыре ядра, тогда 40?

4b9b3361

Ответ 1

Ответ заключается в том, что это верхний предел для всей параллельной операции, независимо от количества ядер.

Таким образом, даже если вы не используете CPU, потому что вы ожидаете ввода-вывода или блокировки, никакие дополнительные задачи не будут выполняться параллельно, а только максимум, который вы укажете.

Чтобы узнать это, я написал этот фрагмент тестового кода. Существует искусственный замок, чтобы стимулировать TPL использовать больше потоков. То же самое произойдет, когда ваш код ожидает ввода-вывода или базы данных.

class Program
{
    static void Main(string[] args)
    {
        var locker = new Object();
        int count = 0;
        Parallel.For
            (0
             , 1000
             , new ParallelOptions { MaxDegreeOfParallelism = 2 }
             , (i) =>
                   {
                       Interlocked.Increment(ref count);
                       lock (locker)
                       {
                           Console.WriteLine("Number of active threads:" + count);
                           Thread.Sleep(10);
                        }
                        Interlocked.Decrement(ref count);
                    }
            );
    }
}

Если я не укажу MaxDegreeOfParallelism, ведение журнала консоли показывает, что одновременно работает около 8 задач. Вот так:

Number of active threads:6
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:6
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7
Number of active threads:7

Он начинает снижаться, увеличивается с течением времени, и в конце он пытается запустить 8 одновременно.

Если я ограничу его каким-либо произвольным значением (скажем, 2), я получаю

Number of active threads:2
Number of active threads:1
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2
Number of active threads:2

О, и это на четырехъядерной машине.

Ответ 2

Например, есть ли вообще что-то вроде: если у процессора есть два ядра, тогда используйте 20, если у процессора четыре ядра, тогда 40?

Вы можете сделать это, чтобы сделать parallelism в зависимости от количества ядер процессора:

var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Parallel.ForEach(sourceCollection, options, sourceItem =>
{
    // do something
});

Однако более новый процессор имеет тенденцию использовать гиперпоточность для моделирования дополнительных ядер. Поэтому, если у вас есть четырехъядерный процессор, тогда Environment.ProcessorCount, вероятно, сообщит об этом как о 8 ядрах. Я обнаружил, что если вы установите для parallelism учет для симулированных ядер, то это фактически замедлит другие потоки, такие как потоки пользовательского интерфейса.

Итак, хотя операция завершится немного быстрее, пользовательский интерфейс приложения может испытывать значительное отставание в течение этого времени. Разделение "Environment.ProcessorCount" на 2, похоже, достигает одинаковой скорости обработки, сохраняя при этом процессор доступным для потоков пользовательского интерфейса.

Ответ 3

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

Ответ 4

он устанавливает количество потоков для параллельной работы...