Дросселирование процессора в C ++ - PullRequest
40 голосов
/ 05 августа 2008

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

Сейчас я нашел наиболее трудоемкий цикл в потоке (он выполняет только сжатие) и использую GetTickCount() и Sleep() с жестко закодированными значениями. Это гарантирует, что цикл продолжается в течение определенного периода времени, а затем спит в течение определенного минимального времени. Это более или менее выполняет работу, то есть гарантирует, что поток не будет использовать более 50% процессорного времени.
Однако поведение зависит от количества ядер ЦП (огромный недостаток) и просто безобразно (меньший недостаток :)).
Есть идеи?

Ответы [ 5 ]

18 голосов
/ 06 сентября 2008

Я не знаю ни одного API, который бы заставлял планировщик ОС делать то, что вы хотите (даже если ваш поток имеет приоритет бездействия, если нет готовых потоков с более высоким приоритетом, ваш будет работать). Тем не менее, я думаю, что вы можете импровизировать довольно элегантную функцию регулирования на основе того, что вы уже делаете. По сути (у меня нет удобной машины для Windows):

Выберите количество по умолчанию, в течение которого поток будет спать каждую итерацию. Затем на каждой итерации (или на каждой n-й итерации, когда функция регулирования сама по себе не становится значительной загрузкой ЦП),

  1. Вычисляет количество процессорного времени, использованного вашим потоком с момента последнего вызова функции регулирования (я назову этот dCPU). Вы можете использовать API GetThreadTimes () , чтобы узнать, сколько времени выполнялся ваш поток.
  2. Вычисляет количество реального времени, прошедшего с момента последнего вызова функции регулирования (я назову этот dClock).
  3. dCPU / dClock - процент использования ЦП (одного ЦП). Если оно выше, чем вы хотите, увеличьте время сна, если ниже, уменьшите время сна.
  4. Дайте вашей нити спать в течение вычисленного времени.

В зависимости от того, как ваш сторожевой таймер вычисляет загрузку процессора, вы можете использовать GetProcessAffinityMask () , чтобы узнать, сколько процессоров имеет система. dCPU / (dClock * CPU) - это процент общего доступного времени CPU.

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

4 голосов
/ 05 августа 2008

В linux вы можете изменить приоритет планирования потока с помощью nice ().

2 голосов
/ 06 сентября 2008

Проблема в том, что не хочется оставлять процессор простаивающим, пока у вас есть работа. Обычно вы устанавливаете фоновую задачу с приоритетом IDLE и позволяете операционной системе планировать все время ЦП, которое не используется интерактивными задачами.

Мне кажется, что проблема в сторожевом процессе.

Если ваша фоновая задача связана с ЦП, то вы хотите, чтобы она использовала все неиспользованное время ЦП для своей задачи.

Может быть, вам стоит взглянуть на исправление сторожевой программы?

2 голосов
/ 05 августа 2008

Я не могу придумать какой-либо кроссплатформенный способ того, что вы хотите (или любой гарантированный способ полной остановки), но, поскольку вы используете GetTickCount, возможно, вас не интересует кроссплатформенность:)

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

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

0 голосов
/ 03 января 2018

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

...