Estou criando um mecanismo de jogo 2D simples e quero atualizar e renderizar os sprites em diferentes threads, para aprender como isso é feito.
Preciso sincronizar o thread de atualização e o de renderização. Atualmente, eu uso duas bandeiras atômicas. O fluxo de trabalho se parece com:
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
Nesta configuração, limito o FPS do thread de renderização ao FPS do thread de atualização. Além disso, eu uso sleep()
para limitar o FPS do thread de renderização e atualização para 60, para que as duas funções de espera não esperem muito tempo.
O problema é:
O uso médio da CPU é de cerca de 0,1%. Às vezes, chega a 25% (em um PC quad core). Isso significa que um encadeamento está aguardando o outro, porque a função de espera é um loop while com uma função de teste e configuração, e um loop while usará todos os recursos da CPU.
Minha primeira pergunta é: existe outra maneira de sincronizar os dois threads? Notei que std::mutex::lock
não use a CPU enquanto espera bloquear um recurso, para que não seja um loop while. Como funciona? Não posso usar std::mutex
porque precisarei travá-los em um segmento e desbloquear em outro.
A outra pergunta é; como o programa é executado sempre a 60 FPS, por que o uso da CPU às vezes aumenta para 25%, o que significa que uma das duas esperas está aguardando muito? (os dois threads são limitados a 60fps, portanto, idealmente, não precisarão de muita sincronização).
Edit: Obrigado por todas as respostas. Primeiro, quero dizer que não inicio um novo thread a cada quadro para renderizar. Eu inicio o loop de atualização e renderização no início. Eu acho que multithreading pode economizar algum tempo: Eu tenho as seguintes funções: FastAlg () e Alg (). Alg () é meu objeto de atualização e objeto de renderização e Fastalg () é minha fila de "envio de renderização para" renderizador "". Em um único encadeamento:
Alg() //update
FastAgl()
Alg() //render
Em dois segmentos:
Alg() //update while Alg() //render last frame
FastAlg()
Portanto, talvez o multithreading economize o mesmo tempo. (na verdade, em um aplicativo matemático simples, onde alg é um algoritmo longo e fastalg é mais rápido)
Sei que dormir não é uma boa ideia, embora nunca tenha tido problemas. Isso vai melhorar?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Mas este será um loop while infinito que usará toda a CPU. Posso usar o sono (um número <15) para limitar o uso? Dessa forma, ele será executado a, por exemplo, 100 fps, e a função de atualização será chamada apenas 60 vezes por segundo.
Para sincronizar os dois threads, usarei waitforsingleobject com createSemaphore, para poder bloquear e desbloquear em threads diferentes (sem usar um loop while), não é?