Как уменьшить загрузку ЦП при интенсивных многопоточных вычислениях

Я реализовал метаэвристический решатель и использовал .NET 4.0 Parallel.For и Parallel.Foreach. Он отлично работает на моей машине среднего уровня. Но поиск слишком интенсивен и потребляет слишком много ресурсов, особенно процессорного времени на младших машинах.

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

Я подумываю поставить Thread.Sleep на методы, так как все потоки на 100% привязаны к ЦП (без ввода-вывода). Снизит ли это интенсивность использования ЦП, которая мне нужна? Есть ли лучшее решение?


person ipoppo    schedule 12.09.2012    source источник
comment
Почему вас волнует, что он потребляет слишком много процессора? Обычно время ЦП в любом случае не используется, а ОС достаточно умна с планированием, поэтому ваше приложение не должно мешать другим процессам в системе.   -  person svick    schedule 12.09.2012
comment
@svick Я бы хотел, чтобы он работал как фоновые приложения. В настоящее время он пытается заморозить всю машину :(   -  person ipoppo    schedule 12.09.2012
comment
Это будет мешать. Если это интенсивно использующее ЦП приложение работает с «нормальными» приоритетами процессов и потоков и имеет достаточное количество потоков, чтобы занять все ядра, влияние на другие приложения, такие как Office, браузеры и т. д., будет заметно для человека на устройствах с низкими характеристиками.   -  person Martin James    schedule 12.09.2012
comment
@dondonchi Это действительно морозит твою машину? Тогда у вас может быть какая-то другая проблема, например, чрезмерная подкачка. Сколько памяти использует ваше приложение?   -  person svick    schedule 12.09.2012
comment
@svick На самом деле не заморожен, но закрыт. Я не особо вникал в это, проверю позже, спасибо.   -  person ipoppo    schedule 12.09.2012
comment
Почему бы вам просто не использовать MaxDegreeOfParallelism для создания ограниченного числа потоков и оставить несколько ядер свободными?   -  person Tudor    schedule 13.09.2012


Ответы (2)


Если вы используете разные темы, я предлагаю следующее:

Thread.Priority = ThreadPriority.BelowNormal

Таким образом, поток получает меньший приоритет.

Редактировать

Хорошо, это решение приемлемо только в том случае, если оно не используется с ThreadPool.

Здесь я не уверен, но как насчет:

Process.ProcessorAffinity
  • Получает или задает процессоры, на которых можно запланировать выполнение потоков в этом процессе.

Если мы ограничим количество ядер, у нас появится больше места для другой работы, верно?

person CodeTherapist    schedule 12.09.2012
comment
Я не думаю, что это хорошее решение, когда вы используете Parallel.For(Each), потому что он использует пул потоков, и эти потоки могут использоваться из других частей процесса. Изменение приоритета всего процесса (а не каждого отдельного потока) было бы лучшим решением. - person svick; 12.09.2012
comment
@svick - да, поэтому они тоже имеют более низкий приоритет. Я не вижу в этом никакой проблемы. Понизить приоритет всего процесса было бы еще проще — явное снижение приоритета потоков пула и т. д. - person Martin James; 12.09.2012
comment
@MartinJames Но что, если другая часть приложения установит нормальный приоритет (может быть, потому, что здесь важна отзывчивость)? Тогда это будет сбивать с толку, потому что вы не будете уверены, какой приоритет имеет текущий поток, если не установите его явно. Из-за этого я думаю, что установка приоритета потока пула потоков никогда не будет правильным решением. - person svick; 12.09.2012
comment
Есть ли способ определить, был ли он запущен на машине с низким ресурсом? - person ipoppo; 12.09.2012
comment
ОП не указал, что приоритеты отдельных потоков изменяются для повышения общей производительности приложения. Если да, то установка более низкого приоритета процесса по-прежнему будет поддерживать иерархию приоритетов отдельных потоков в приложении. Интуитивно (да, я не пробовал с Parallel.For) я не вижу никаких проблем. Эмпирически установка приоритета явных потоков пула на более низкий уровень (например, для повышения производительности графического интерфейса) работает нормально. Вы пробовали это и нашли какие-либо проблемы? - person Martin James; 12.09.2012
comment
Вы можете получить системную информацию с помощью WMI, а затем настроить правильную конфигурацию. - person CodeTherapist; 12.09.2012
comment
Установка приоритета потока для потока из пула — действительно плохая идея. См. blogs.msdn.com. /b/harip/архив/2010/10/11/ - person Peter Ritchie; 13.09.2012
comment
Петр, я прочитал вашу ссылку. Имеет ли это смысл для вас? Так что, если поток пула потоков будет вытеснен, потому что поток с нормальным приоритетом станет готовым - это своего рода точка понижения приоритетов, конечно? Кто-нибудь может объяснить, почему это «действительно плохая идея», когда «действительно плохая идея» является первоначальным требованием? Насколько я вижу, аргумент в ссылке таков: «если вы уменьшите приоритет потока, он будет вытеснен потоком с более высоким приоритетом, который станет готовым» — не совсем новость, не так ли? - person Martin James; 13.09.2012
comment
@Martin James: снижение приоритета потока пула потоков - плохая идея, потому что они должны быть анонимными. Если задача, назначенная потоку, снижает свой приоритет, вы не знаете, какая именно. Тогда вы будете получать задачи, запускаемые случайным образом с низким приоритетом. Я не понимаю, как это может быть полезно. - person Tudor; 13.09.2012
comment
Еще один момент: если снижение приоритетов процесса и/или потока не является ответом на уменьшение влияния долго работающего приложения с интенсивным использованием ЦП на «обычные» приложения с графическим интерфейсом, не интенсивно использующие ЦП (Office, Firefox, IDE, VLC player). ), что? - person Martin James; 13.09.2012
comment
@Tudor - я не знаю, какой механизм использовать в C #, чтобы эффективно понизить приоритет всех потоков пула потоков явным образом. Предположительно, это нужно было бы сделать с помощью какого-то обработчика событий при запуске нового потока пула потоков (есть идеи, кто-нибудь?). Понижение приоритета процесса будет работать - все потоки пула потоков получат более низкий приоритет планирования обычным способом Windows - они будут вытеснены потоками с обычным приоритетом в Office, браузере, медиаплеере и т. д., когда они станут готовы. Все еще не убежден «действительно плохой идеей». - person Martin James; 13.09.2012
comment
@Martin James: Традиционно современные операционные системы (включая Windows) всегда отдавали предпочтение интерактивным приложениям, а не приложениям, привязанным к процессору. Когда пользователь фокусируется на интерактивном приложении, ОС дает ему повышение приоритета, чтобы гарантировать, что оно может вытеснить любую задачу ЦП. На самом деле даже фоновые задачи, выполняющие ввод-вывод, будут автоматически предпочтительнее задач ЦП при поступлении прерывания ввода-вывода. - person Tudor; 13.09.2012
comment
@Tudor - да, я понимаю, что задачам переднего плана графического интерфейса будет присвоен более высокий приоритет и что потоки, подготовленные к вводу-выводу, будут усилены. Это также относится к потокам в приложении с интенсивным использованием ЦП. Довольно легко исследовать влияние приложения, интенсивно использующего ЦП, на основные приложения с графическим интерфейсом — создайте несколько зацикленных потоков, запустите их, запустите Office, Firefox и т. д. и используйте их. Затем попробуйте установить приоритет процесса тяжелого приложения на «Ниже нормального» с помощью диспетчера задач — это действительно заметно для человека. - person Martin James; 13.09.2012
comment
Если вы хотите отключить автоматическое повышение целевого приложения, вы можете использовать Process.PriorityBoostEnabled со значением false. - person CodeTherapist; 13.09.2012

(высовывает голову над парапетом, готовясь быть сбитым множеством минусов..:)

Если вы используете разные темы, я предлагаю следующее:

Thread.Priority = ThreadPriority.BelowNormal

Таким образом, поток получает меньший приоритет.

[Да, это прямая копия ответа C Sharper, но без более поздних правок о потоках пула потоков и сродстве. Если вы считаете, что это хорошая идея - голосуйте за C Sharper, а не за меня].

Либо уменьшите приоритет всего процесса с помощью диспетчера задач или других средств. Это уменьшит «реальный» приоритет планирования для всех потоков в процессе (включая потоки пула потоков «очень плохой идеи») и улучшит взаимодействие с пользователем для других приложений, которые не интенсивно используют ЦП, но должны быстро реагировать, когда им нужно сделать что-то. Тяжелое приложение с более низким приоритетом по-прежнему будет поглощать весь оставшийся процессор и, если вы решите не редактировать данные о продажах в этом месяце или смотреть последние незаконно загруженные фильмы, защищенные авторским правом, будет работать так же, как если бы оно работало с обычным приоритетом.

person Martin James    schedule 13.09.2012