Моя многопоточная игра все время работает на 100% CPU. Как я могу управлять работой потоков, чтобы уменьшить нагрузку на процессор?

0

У меня есть игра DirectX, которая генерирует 2 потоковых потока в двухъядерной системе: 1 для геймплея/рендеринга (обычно разбивается на собственные потоки на четырехъядерном процессоре) и 1 другой поток, который процедурно генерирует игровой мир. Я считаю, что мое аудио промежуточное ПО также порождает собственные потоки для воспроизведения SFX и музыки.

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

Возможно ли/целесообразно вручную управлять тем, насколько активен поток? Если да, то какие стратегии я могу использовать для этого? Я все время вижу, что люди говорят, что функции sleep() на самом деле не рекомендуются, но я действительно не знаю, что еще делать.

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

  • 4
    Сначала задайте себе более простой вопрос: что бы означало, что простая однопоточная программа не работает при 100% загрузке процессора? Как заставить программу не запускаться?
  • 0
    Вы всегда лучше обслуживаете, выполняя традиционное профилирование / оптимизацию.
Показать ещё 9 комментариев
Теги:
multithreading
boost-thread

3 ответа

5
Лучший ответ

Получение 100% -ного использования процессора означает, что у вас нет игровых часов. Вероятно, вы получаете кадры так же быстро, как позволяет машина. Все еще довольно сложно получить 100% точно, если вы используете несколько потоков, что указывает на то, что вы также не синхронизируете потоки.

Это, вероятно, потребует довольно радикальной перезаписи. Темп должен быть установлен основным циклом рендеринга, который копирует задний буфер в видеоадаптер. Он устанавливает ваш целевой FPS, кадры в секунду. Нередко вы используете для этого вертикальный интервал гашения, он решает проблемы с разрывом, гарантируя, что монитор будет обновляться в точное время. Который автоматически получает цикл рендеринга с частотой обновления монитора. Как правило, 60 раз в секунду на ЖК-мониторах. Таймер - альтернатива. Это предотвращает сжигание основной нити на 100%, если предположить, что она может идти в ногу с FPS.

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

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

Звук должен быть более простой проблемой для решения, вам просто нужно сохранить буферы звуковой карты заполненными достаточными данными, чтобы выжить на пару фраз, стоящих за звук.

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

1

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

Это "что-то" может быть так же просто, как временно установить приоритет аудиопотока на более высокое значение. Подумайте, почему бы не установить его с самого начала? Это решило бы все проблемы, не так ли? Еще лучше, просто снимите приоритет мировой генераторной нити.

  • 0
    Спасибо за ответ - да, это, вероятно, гораздо более разумный подход. К сожалению, у меня нет доступа к аудиобуферу / потоку, так что, возможно, лучшим вариантом будет нормальная оптимизация / переоценка моего промежуточного программного обеспечения. Относительно приоритета потока - это то, что зависит от API или от платформы? Первое, что я нашел, - это функция SetThreadPriority () в Windows. Я на правильном пути?
  • 0
    @Raptormeat Я не вижу разницы между API и платформой. Windows SDK раньше раньше назывался Platform SDK. Но да, SetThreadPriority - это функция. Не совсем уверен, почему вы приняли ответ, потому что, кажется, вы хотели бы больше идей. Вопросы с принятым ответом обычно больше не имеют ответов.
Показать ещё 1 комментарий
0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню