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

Возможно ли изменить parallelOptions.MaxDegreeOfParallelism во время выполнения Parallel.ForEach

Я запускаю многопоточный цикл:

protected ParallelOptions parallelOptions = new ParallelOptions();

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

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

parallelOptions.MaxDegreeOfParallelism = 5;

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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