Ich erstelle eine einfache 2D-Spiel-Engine und möchte die Sprites in verschiedenen Threads aktualisieren und rendern, um zu erfahren, wie es gemacht wird.
Ich muss den Update-Thread und den Render-Thread synchronisieren. Derzeit verwende ich zwei Atomflags. Der Workflow sieht ungefähr so aus:
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 diesem Setup beschränke ich die FPS des Render-Threads auf die FPS des Update-Threads. Außerdem beschränke ich sleep()
die FPS des Render- und Update-Threads auf 60, damit die beiden Wartefunktionen nicht lange warten.
Das Problem ist:
Die durchschnittliche CPU-Auslastung liegt bei 0,1%. Manchmal sind es bis zu 25% (in einem Quad-Core-PC). Dies bedeutet, dass ein Thread auf den anderen wartet, da die Wartefunktion eine while-Schleife mit einer Test- und Set-Funktion ist und eine while-Schleife alle Ihre CPU-Ressourcen verwendet.
Meine erste Frage lautet: Gibt es eine andere Möglichkeit, die beiden Threads zu synchronisieren? Ich habe festgestellt, dass std::mutex::lock
die CPU nicht verwendet wird, während sie darauf wartet, eine Ressource zu sperren, sodass es sich nicht um eine while-Schleife handelt. Wie funktioniert es? Ich kann nicht verwenden, std::mutex
da ich sie in einem Thread sperren und in einem anderen Thread entsperren muss.
Die andere Frage ist; Da das Programm immer mit 60 FPS ausgeführt wird, warum springt die CPU-Auslastung manchmal auf 25%, was bedeutet, dass eine der beiden Wartezeiten viel wartet? (Die beiden Threads sind beide auf 60 fps begrenzt, sodass sie im Idealfall nicht viel Synchronisation benötigen.)
Edit: Danke für alle Antworten. Zuerst möchte ich sagen, dass ich nicht in jedem Frame einen neuen Thread zum Rendern starte. Ich starte sowohl die Aktualisierungs- als auch die Renderschleife am Anfang. Ich denke, Multithreading kann einige Zeit sparen: Ich habe die folgenden Funktionen: FastAlg () und Alg (). Alg () ist sowohl mein Update-Objekt als auch mein Render-Objekt und Fastalg () ist meine "Render-Warteschlange an" Renderer "senden. In einem einzigen Thread:
Alg() //update
FastAgl()
Alg() //render
In zwei Threads:
Alg() //update while Alg() //render last frame
FastAlg()
Vielleicht kann Multithreading gleichzeitig Zeit sparen. (Tatsächlich in einer einfachen mathematischen Anwendung, in der alg ein langer Algorithmus und fastalg ein schnellerer Algorithmus ist)
Ich weiß, dass Schlaf keine gute Idee ist, obwohl ich nie Probleme habe. Wird das besser?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Dies ist jedoch eine Endlosschleife, die die gesamte CPU belegt. Kann ich den Schlaf (eine Zahl <15) verwenden, um die Nutzung einzuschränken? Auf diese Weise wird es beispielsweise mit 100 fps ausgeführt, und die Aktualisierungsfunktion wird nur 60 Mal pro Sekunde aufgerufen.
Um die beiden Threads zu synchronisieren, verwende ich waitforsingleobject mit createSemaphore, damit ich in verschiedenen Threads sperren und entsperren kann (ohne Verwendung einer while-Schleife), nicht wahr?