Sto creando un semplice motore di gioco 2D e voglio aggiornare e renderizzare gli sprite in diversi thread, per imparare come è fatto.
Devo sincronizzare il thread di aggiornamento e quello di rendering. Attualmente uso due bandiere atomiche. Il flusso di lavoro è simile al seguente:
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
In questa configurazione, limito l'FPS del thread di rendering all'FPS del thread di aggiornamento. Inoltre, utilizzo sleep()
per limitare il rendering e l'aggiornamento dell'FPS del thread a 60, quindi le due funzioni di attesa non attenderanno molto tempo.
Il problema è:
L'utilizzo medio della CPU è di circa lo 0,1%. A volte arriva fino al 25% (in un PC quad core). Significa che un thread è in attesa dell'altro perché la funzione wait è un ciclo while con una funzione test e set e un ciclo while utilizzerà tutte le risorse della CPU.
La mia prima domanda è: c'è un altro modo per sincronizzare i due thread? Ho notato che std::mutex::lock
non usano la CPU mentre è in attesa di bloccare una risorsa, quindi non è un ciclo while. Come funziona? Non posso usarlo std::mutex
perché dovrò bloccarli in un thread e sbloccarli in un altro thread.
L'altra domanda è; dal momento che il programma funziona sempre a 60 FPS perché a volte il suo utilizzo della CPU passa al 25%, il che significa che una delle due attese è in attesa molto? (i due thread sono entrambi limitati a 60 fps, quindi idealmente non avranno bisogno di molta sincronizzazione).
Modifica: grazie per tutte le risposte. Per prima cosa voglio dire che non inizio un nuovo thread ogni frame per il rendering. Inizio sia l'aggiornamento che il ciclo di rendering all'inizio. Penso che il multithreading possa far risparmiare un po 'di tempo: ho le seguenti funzioni: FastAlg () e Alg (). Alg () è sia il mio Update obj che render obj e Fastalg () è la mia "invia la coda di rendering a" renderer "". In un singolo thread:
Alg() //update
FastAgl()
Alg() //render
In due thread:
Alg() //update while Alg() //render last frame
FastAlg()
Quindi forse il multithreading può risparmiare allo stesso tempo. (in realtà lo fa in una semplice applicazione matematica, dove alg è un algoritmo lungo e fastalg uno più veloce)
So che dormire non è una buona idea, anche se non ho mai avuto problemi. Sarà meglio?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Ma questo sarà un ciclo while infinito che utilizzerà tutta la CPU. Posso usare sleep (un numero <15) per limitare l'utilizzo? In questo modo verrà eseguito, ad esempio, a 100 fps e la funzione di aggiornamento verrà chiamata solo 60 volte al secondo.
Per sincronizzare i due thread userò waitforsingleobject con createSemaphore in modo da poter bloccare e sbloccare in thread diversi (senza usare un ciclo while), vero?