Увеличить количество запущенных потоков в Parallel.For

Я только что сделал пример многопоточности, используя эту ссылку, например ниже:

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);            
int count = 0;
Parallel.For(0, 50000, options,(i, state) =>
{
            count++;                
});

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
Console.ReadKey();

Это дает мне 15 потоков до Parellel.For и после этого дает мне только 17 потоков. Таким образом, только 2 потока заняты Parelnel.For.

Затем я создал еще один пример кода, используя эту ссылку, как показано ниже:

var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Console.WriteLine("MaxDegreeOfParallelism : {0}", Environment.ProcessorCount * 10);
Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);            
int count = 0;
Parallel.For(0, 50000, options,(i, state) =>
{
            count++;                
});

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
Console.ReadKey();

В приведенном выше коде я установил MaxDegreeOfParallelism, где он устанавливает 40, но по-прежнему использует те же потоки для Parallel.For.

Итак, как я могу увеличить текущий поток для Parallel.For?


person Ravi Solanki    schedule 06.04.2016    source источник
comment
Из MSDN: по умолчанию For и ForEach будут использовать столько потоков, сколько предоставляет базовый планировщик, поэтому изменение MaxDegreeOfParallelism по умолчанию ограничивает только количество одновременно используемых задач. Это используется для ограничения количества потоков, чтобы, насколько я могу судить, не использовать их слишком много.   -  person o_weisman    schedule 06.04.2016
comment
Я столкнулся с проблемой, что некоторые числа пропускаются внутри Parallel.For, когда я выполняю внутри него некоторые тяжелые и сложные функции. Итак, здесь я хочу увеличить максимальный поток и переопределить проблему пропуска. Я пробовал с lock, но думаю, что это не даст мне параллелизма, которого я хочу.   -  person Ravi Solanki    schedule 06.04.2016


Ответы (3)


Параллельные циклы используют аппаратные ядра ЦП. Если ваш ЦП имеет 2 ядра, это максимальная степень параллелизма, которую вы можете получить на своем компьютере.

Взято из MSDN:

Что ожидать

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

Дальнейшее чтение:

person Matías Fidemraizer    schedule 06.04.2016
comment
Это означает, что мне не нужно заботиться о MaxDegreeOfParallelism, поскольку ЦП уже позаботился о количестве доступных ядер. Правильно? - person Ravi Solanki; 06.04.2016
comment
@RaviSolanki Чем больше ядер у вашего процессора, тем больше параллельных задач ваше приложение может выполнять одновременно. - person Matías Fidemraizer; 06.04.2016
comment
Интересно, как я уже упоминал свой запрос выше, я столкнулся с проблемой, что некоторые числа пропускаются внутри Parallel.For, когда я выполняю в нем некоторые тяжелые и сложные функции. Итак, здесь я хочу увеличить максимальный поток и переопределить проблему пропуска. Я пробовал с блокировкой, но думаю, что это не даст мне параллелизма, который я хочу. - person Ravi Solanki; 06.04.2016
comment
@RaviSolanki В параллельных циклах итерации выполняются не по порядку. Итерации не пропускаются, а выполняются неупорядоченно - person Matías Fidemraizer; 06.04.2016
comment
Да, я понимаю, что это выполняется в случайном порядке. Я подсчитал общую операцию, выполненную внутри него, где я установил 50000 итераций, но после параллелизма. Поскольку я напечатал общее количество выполненных итераций, и он показывает мне 37000 что-то число. Я что-то упускаю? - person Ravi Solanki; 06.04.2016
comment
@RaviSolanki Ну, я не знаю, что происходит в вашем конкретном случае ... Кажется, я уже ответил на ваш вопрос, в вашем коде должна быть какая-то проблема, я сомневаюсь, что вы установили Parallel.For для выполнения 50 тыс. Итераций а получилось всего 37к... - person Matías Fidemraizer; 06.04.2016
comment
Может быть, позвольте мне еще раз пройтись по всему коду. Спасибо !! - person Ravi Solanki; 06.04.2016
comment
@RaviSolanki Нет проблем!! - person Matías Fidemraizer; 06.04.2016

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

Вы говорите что-то вроде: «Моя машина трясется, когда я еду слишком быстро. Я пытаюсь избежать этого, двигаясь еще быстрее». Это не имеет никакого смысла. Вам нужно починить машину, а не изменить скорость.

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

Использование блокировки — это один из вариантов, и его проще всего исправить. Но также трудно сделать его эффективным. Что вам нужно, так это блокировать только на короткое время каждую итерацию.

Существуют и другие способы обеспечения безопасности потоков, включая использование Interlocked. , перегружает Parallel.For, использующих локальные данные потока, и использует подходы, отличные от Parallel.For(), например Поток данных PLINQ или TPL.


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

  • Для вычислений, связанных с процессором, нет смысла использовать больше потоков, чем количество ядер вашего процессора. Использование большего количества потоков на самом деле обычно приводит к более медленному коду, поскольку переключение между потоками имеет некоторые накладные расходы.
  • Я не думаю, что вы можете измерить количество потоков, используемых Parallel.For() таким образом. Parallel.For() использует пул потоков, и вполне возможно, что до начала цикла в пуле уже есть какие-то потоки.
person svick    schedule 06.04.2016
comment
Ценю ваши ответы! Локальные переменные потока весьма полезны для расчета итераций, выполняемых Parallel.For. Я также прошел TPL, который кажется мне полезным. Я реализовал следующий код. Так что мне нужно реализовать какую-либо потокобезопасность и здесь? var tasks = new Task[Count]; for (var i = 0; i < Count; i++) { tasks[i] = Task.Factory.StartNew(() => SomeHeavyOpertaion()); } Task.WaitAll(tasks); - person Ravi Solanki; 07.04.2016
comment
@RaviSolanki Это очень сильно зависит от того, что делает SomeHeavyOpertaion(). - person svick; 07.04.2016
comment
Я получаю поток HTML из нескольких URL-адресов (в моем случае это около 47 КБ) и сохраняю в хранилище BLOB-объектов Azure. - person Ravi Solanki; 07.04.2016

Параллельные циклы дадут вам неправильный результат для операций суммирования без блокировок, поскольку результат каждой итерации зависит от одной переменной «Count», а значение «Count» в параллельном цикле непредсказуемо. Однако использование блокировок в параллельных циклах не обеспечивает фактического параллелизма. поэтому вам следует попробовать что-то еще для тестирования параллельного цикла вместо суммирования.

person Abdul Majid    schedule 26.02.2017