Je crée un moteur de jeu 2D simple et je veux mettre à jour et rendre les sprites dans différents threads, pour savoir comment cela se fait.
J'ai besoin de synchroniser le fil de mise à jour et celui de rendu. Actuellement, j'utilise deux drapeaux atomiques. Le flux de travail ressemble à ceci:
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
Dans cette configuration, je limite le FPS du fil de rendu au FPS du fil de mise à jour. De plus, j'utilise sleep()
pour limiter à la fois le rendu et la mise à jour du FPS du thread à 60, de sorte que les deux fonctions d'attente n'attendront pas beaucoup de temps.
Le problème est:
L'utilisation moyenne du processeur est d'environ 0,1%. Parfois, cela peut aller jusqu'à 25% (dans un PC quadricœur). Cela signifie qu'un thread attend l'autre car la fonction wait est une boucle while avec une fonction test et set, et une boucle while utilise toutes vos ressources CPU.
Ma première question est: existe-t-il une autre façon de synchroniser les deux threads? J'ai remarqué que std::mutex::lock
n'utilisez pas le CPU pendant qu'il attend pour verrouiller une ressource, ce n'est donc pas une boucle while. Comment ça marche? Je ne peux pas l'utiliser std::mutex
car je devrai les verrouiller dans un thread et les déverrouiller dans un autre thread.
L'autre question est; comme le programme tourne toujours à 60 FPS, pourquoi son utilisation du processeur passe-t-elle parfois à 25%, ce qui signifie que l'une des deux attentes attend beaucoup? (les deux threads sont tous deux limités à 60 images par seconde, donc ils n'auront idéalement pas besoin de beaucoup de synchronisation).
Edit: Merci pour toutes les réponses. Je veux d'abord dire que je ne démarre pas un nouveau thread à chaque image pour le rendu. Je démarre la boucle de mise à jour et de rendu au début. Je pense que le multithreading peut gagner du temps: j'ai les fonctions suivantes: FastAlg () et Alg (). Alg () est à la fois mon obj de mise à jour et mon obj de rendu et Fastalg () est ma "file d'attente de rendu d'envoi vers" renderer "". En un seul fil:
Alg() //update
FastAgl()
Alg() //render
En deux fils:
Alg() //update while Alg() //render last frame
FastAlg()
Alors peut-être que le multithreading peut vous faire gagner du temps. (en fait, dans une application mathématique simple, c'est le cas, où alg est un long algorithme et fastalg un plus rapide)
Je sais que le sommeil n'est pas une bonne idée, même si je n'ai jamais eu de problèmes. Est-ce que ce sera mieux?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Mais ce sera une boucle while infinie qui utilisera tout le CPU. Puis-je utiliser le mode veille (un nombre <15) pour limiter l'utilisation? De cette façon, il fonctionnera à, par exemple, 100 images par seconde, et la fonction de mise à jour sera appelée seulement 60 fois par seconde.
Pour synchroniser les deux threads, j'utiliserai waitforsingleobject avec createSemaphore afin de pouvoir verrouiller et déverrouiller dans différents threads (sans utiliser de boucle while), n'est-ce pas?