Я создаю простой 2D игровой движок и хочу обновить и визуализировать спрайты в разных потоках, чтобы узнать, как это делается.
Мне нужно синхронизировать поток обновления и рендер. В настоящее время я использую два атомных флага. Рабочий процесс выглядит примерно так:
Thread 1 -------------------------- Thread 2
Update obj ------------------------ wait for swap
Create queue ---------------------- render the queue
Wait for render ------------------- notify render done
Swap render queues ---------------- notify swap done
В этой настройке я ограничиваю FPS потока рендеринга FPS потока обновления. Кроме того, я использую sleep()
для ограничения как рендеринга, так и обновления FPS потока до 60, поэтому две функции ожидания не будут ждать много времени.
Проблема в:
Среднее использование процессора составляет около 0,1%. Иногда доходит до 25% (в четырехъядерном ПК). Это означает, что поток ожидает другого, потому что функция wait является циклом while с функцией test и set, а цикл while будет использовать все ресурсы вашего ЦП.
Мой первый вопрос: есть ли другой способ синхронизации двух потоков? Я заметил, что std::mutex::lock
не используйте процессор, пока он ожидает блокировки ресурса, поэтому он не является циклом while. Как это работает? Я не могу использовать, std::mutex
потому что мне нужно будет заблокировать их в одном потоке и разблокировать в другом потоке.
Другой вопрос: Поскольку программа работает всегда со скоростью 60 FPS, почему иногда загрузка процессора увеличивается до 25%, а это означает, что один из двух ожиданий ждет много? (оба потока ограничены 60 кадрами в секунду, поэтому в идеале им не нужно много синхронизации).
Редактировать: Спасибо за все ответы. Сначала я хочу сказать, что я не запускаю новый поток каждый кадр для рендера. Я запускаю цикл обновления и рендеринга в начале. Я думаю, что многопоточность может сэкономить время: у меня есть следующие функции: FastAlg () и Alg (). Alg () - это мой объект обновления obj и render obj, а Fastalg () - это моя очередь отправки рендера для renderer. В одной теме:
Alg() //update
FastAgl()
Alg() //render
В два потока:
Alg() //update while Alg() //render last frame
FastAlg()
Так что, возможно, многопоточность может сэкономить время. (на самом деле это происходит в простом математическом приложении, где alg - длинный алгоритм, а быстрый - более быстрый)
Я знаю, что сон не очень хорошая идея, хотя у меня никогда не было проблем. Будет ли это лучше?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Но это будет бесконечный цикл while, который будет использовать весь процессор. Могу ли я использовать сон (число <15), чтобы ограничить использование? Таким образом, он будет работать, например, со скоростью 100 кадров в секунду, а функция обновления будет вызываться всего 60 раз в секунду.
Для синхронизации двух потоков я буду использовать объект waitforsingle с createSemaphore, чтобы иметь возможность блокировать и разблокировать в другом потоке (без использования цикла while), не так ли?