Estoy creando un motor de juego 2D simple y quiero actualizar y renderizar los sprites en diferentes hilos, para aprender cómo se hace.
Necesito sincronizar el hilo de actualización y el de render. Actualmente, uso dos banderas atómicas. El flujo de trabajo se parece a:
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
En esta configuración, limito el FPS del hilo de renderizado al FPS del hilo de actualización. Además, uso sleep()
para limitar tanto el renderizado como la actualización del FPS del hilo a 60, por lo que las dos funciones de espera no esperarán mucho tiempo.
El problema es:
El uso promedio de la CPU es de alrededor del 0.1%. A veces sube hasta un 25% (en una PC de cuatro núcleos). Significa que un subproceso está esperando al otro porque la función de espera es un bucle while con una función de prueba y configuración, y un bucle while utilizará todos los recursos de su CPU.
Mi primera pregunta es: ¿hay otra forma de sincronizar los dos hilos? Noté que std::mutex::lock
no use la CPU mientras está esperando bloquear un recurso, por lo que no es un ciclo while. ¿Como funciona? No puedo usar std::mutex
porque tendré que bloquearlos en un hilo y desbloquearlos en otro hilo.
La otra pregunta es; Dado que el programa se ejecuta siempre a 60 FPS, ¿por qué a veces su uso de CPU salta al 25%, lo que significa que uno de los dos espera mucho? (los dos hilos están limitados a 60 fps, por lo que idealmente no necesitarán mucha sincronización).
Editar: Gracias por todas las respuestas. Primero quiero decir que no comienzo un nuevo hilo en cada cuadro para renderizar. Comienzo tanto la actualización como el bucle de renderizado al principio. Creo que el subprocesamiento múltiple puede ahorrar algo de tiempo: tengo las siguientes funciones: FastAlg () y Alg (). Alg () es mi obj de actualización y obj de render y Fastalg () es mi "cola de envío de render a" renderizador ". En un solo hilo:
Alg() //update
FastAgl()
Alg() //render
En dos hilos:
Alg() //update while Alg() //render last frame
FastAlg()
Entonces, quizás el multiproceso puede ahorrar el mismo tiempo. (en realidad, en una aplicación matemática simple, sí, donde alg es un algoritmo largo y es más rápido)
Sé que dormir no es una buena idea, aunque nunca he tenido problemas. ¿Será esto mejor?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Pero este será un ciclo while infinito que usará toda la CPU. ¿Puedo usar el modo de suspensión (un número <15) para limitar el uso? De esta manera, se ejecutará, por ejemplo, a 100 fps, y la función de actualización se llamará solo 60 veces por segundo.
Para sincronizar los dos hilos, usaré waitforsingleobject con createSemaphore para poder bloquear y desbloquear diferentes hilos (sin usar un bucle while), ¿no?