Как уменьшить использование CPU программы?

Я написал многопоточную программу, которая выполняет некоторые тяжелые вычисления процессора с большим количеством операций с плавающей запятой. Более конкретно, это программа, которая сравнивает последовательности анимации кадр за кадром. Т. е. он сравнивает данные кадра из анимации A со всеми кадрами в анимации B, для всех кадров в анимации A. Я выполняю эту интенсивную операцию для разных анимаций параллельно, поэтому программа может работать на паре A-B, паре B-C и паре C-A параллельно. Программа использует QtConcurrent и функция "map", которая отображает контейнер с движениями на функцию. QtConcurrent управляет пулом потоков для меня, я работаю над четырехъядерным процессором Intel, поэтому он порождает 4 потока.

теперь проблема в том, что мой процесс разрушает мой процессор. Использование 100% постоянно, и я фактически получаю синий экран смерти, если я запускаю свою программу на достаточно большом наборе движений (ошибка страницы в области без страницы). Я подозреваю, что это потому, что мой компьютер разогнан. Однако, может ли это быть из-за того, как я закодировал свою программу? Некоторые очень интенсивные инструменты benchamrking, которые я использовал для проверки стабильности моей машины, никогда не разбивали мой компьютер. Есть ли способ контролировать, как моя программа использует мой процессор для снижения нагрузки? Или, может быть, я неправильно понял свою проблему?

13 ответов


здесь есть несколько отличных ответов.

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

чтобы провести аналогию с междугородней автогонкой, есть два способа попытаться выиграть:

  1. сделать автомобиль идти быстрее
  2. сделать меньше остановок и боковых поездок

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

чтобы найти потерянные циклы в вашей программе, как сказал Кеннет Кокран, никогда не угадайте. Если вы что-то исправите, не доказав, что это проблема, вы инвестируете в догадку.

популярный способ найти проблемы с производительностью-использовать профилировщики.

тем не менее, я делаю это много, и мой метод таков: http://www.wikihow.com/Optimize-Your-Program%27s-Performance


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

Это также может быть какая-то довольно странная ошибка памяти, где вы повреждаете свою ОЗУ таким образом, что Windows (я думаю, что ОС, из-за BSOD) не может восстановить больше (очень маловероятно, но кто знает).

другая возможность, о которой я могу думать, это то, что у вас есть какая-то ошибка в вашем threading-реализация, которая убивает windows.

но сначала я бы посмотрел на проблему разгона...


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

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


Я подозреваю, что это потому, что мой компьютер разогнан.

Это определенно возможно. Попробуйте установить его на нормальную скорость на некоторое время.

может быть, это из-за того, как я закодировал свою программу?

программа, работающая в пользовательском режиме, вряд ли вызовет BSOD.


Я бы сказал, что вы не используете 3-ядерную машину (или 4, учитывая 100% использование), и распараллеливание активно повредит вашей производительности, если вы используете больше потоков, чем ядер. Принять только один поток на ядро процессора, и что бы вы ни делали, никогда не имеют доступа к данным разными потоками одновременно. Алгоритмы блокировки кэша в большинстве многоядерных процессоров абсолютно убивают вашу производительность. В этом случае на N-core CPU, обрабатывающем L-кадровые анимации, я бы использовал резьба 1 на рамах 0-(L/N), резьба 2 на рамах(L/N) - (2*L/N), ... поток N на кадрах ((N-1)*L/N)-L. выполните различные комбинации (A-B, B-C, C-A) последовательно, чтобы вы не колотили свой кеш, также должно быть проще кодировать.

в качестве примечания? Настоящий вычисление такой должны используйте 100% CPU, это означает, что он идет так быстро, как может.


наиболее вероятной причиной нестабильности является разгон. С любым интенсивным алгоритмом процессора будет некоторая ОБМОЛОТКА процессора. Разгон не выдерживает, я бы нашел хороший профилировщик производительности, чтобы найти узкие места производительности. Никогда не угадаешь, в чем проблема. Вы можете потратить месяцы на оптимизацию чего-то, что не влияет на производительность или хуже производительность может даже уменьшиться.


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

вероятно, у вас есть ошибка.


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

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


с отсутствием кода ошибки BSOD(полезно для поиска) немного сложнее помочь вам с этим.

вы можете попробовать физически переустановить свою память ((выньте ее и поместите). Я и некоторые другие, кого я знаю, работали на нескольких машинах, где это было необходимо. Например, я однажды пытался обновить OS X на машине, и он продолжал сбой... наконец я вытащил воспоминание и бросил его обратно, и все было в порядке.


Sleep(1); сократит использование процессора вдвое. Я столкнулся с той же проблемой, работая с алгоритмом интенсивного процессора.


Если ваш процессор имеет два ядра или более, вы можете перейти в Диспетчер задач и перейти к процессам и щелкните правой кнопкой мыши на имени программы и нажмите Set affinity и установите программу для использования меньшего количества ядер.

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


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

Ну, если вы создаете несколько потоков, каждый из которых несет тяжелые операции с плавающей запятой, то, безусловно, ваш ЦП дойдет до 100%.

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


Если в платформе Windows, поместите после некоторой работы один вызов функции, чтобы сообщить CPU, который вы хотите сделать cpu для других процессов. Сделайте вызов функции сна, как это:

Slepp ( 0 );