Можно ли изменить parallelOptions.MaxDegreeOfParallelism во время выполнения Parallel.ForEach - PullRequest
18 голосов
/ 14 сентября 2010

Я выполняю многопоточный цикл:

protected ParallelOptions parallelOptions = new ParallelOptions();

parallelOptions.MaxDegreeOfParallelism = 2;
Parallel.ForEach(items, parallelOptions, item =>
{
// Loop code here
});

Я хочу изменить параллелизм.MaxDegreeOfParallelism при выполнении параллельного цикла, чтобы уменьшить или увеличить количество потоков.*

Кажется, это не увеличивает потоки.У кого-нибудь есть идеи?

Ответы [ 2 ]

6 голосов
/ 14 сентября 2010

Проблема даже с попытками сделать это заключается в том, что это сложная проблема. Для начала, как вы вообще надежно наблюдаете за использованием процессора и диска? Редакция выборки ЦП даст плохое представление о том, что на самом деле происходит, а выборка диска еще сложнее. Во-вторых, какова гранулярность ваших задач и как часто вы можете быстро и реально изменить число запущенных. В-третьих, все быстро меняется со временем, поэтому вам нужно применить какую-то фильтрацию к своим наблюдениям. В-четвертых, идеальное количество потоков будет зависеть от процессора, на котором фактически выполняется код. В-пятых, если вы выделите слишком много потоков, вы будете перебивать их, а не выполнять полезную работу.

См. http://msdn.microsoft.com/en-us/magazine/ff960958.aspx для обсуждения того, как Пул потоков в .NET справляется со сложной задачей определения количества используемых потоков.

Вы также можете использовать рефлектор и взглянуть на код, который TPL использует для распределения потоков и во избежание ненужного переключения контекста - это сложно и даже не учитывает доступ к диску!

Вместо этого вы можете попробовать выполнить задачи в потоке с более низким приоритетом (создать собственный TaskScheduler, который будет запускать потоки с приоритетом ниже нормального, на самом деле довольно просто). Это, по крайней мере, гарантирует, что вы сможете запустить 100% CPU без ущерба для остальной системы. Неразбериха с приоритетами потоков сама по себе чревата проблемами, но если это чисто фоновая задача, она может быть простой и может помочь.

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

Вы также можете посмотреть на SetPriorityClass как способ информирования ОС о том, что ваш процесс менее важен, чем другие приложения, работающие в системе, см. Как повысить приоритет ввода / вывода процесса? для дополнительной информации. Но это предполагает, что весь ваш процесс менее важен, а не только эта его часть.

3 голосов
/ 14 сентября 2010

Я бы не ожидал, что можно будет изменить степень параллелизма после того, как вы позвоните ForEach.Насколько я понимаю, ForEach собирается определить, сколько потоков он может создать, создать такое количество разделов и создать потоки для работы с этими разделами.Нет смысла говорить: «Ой, подождите, он изменил наше распределение ресурсов, позвольте мне переразбить массив и перераспределить потоки».

...