Tworzę prosty silnik do gier 2D i chcę zaktualizować i renderować duszki w różnych wątkach, aby dowiedzieć się, jak to zrobić.
Muszę zsynchronizować wątek aktualizacji i renderowania. Obecnie używam dwóch flag atomowych. Przepływ pracy wygląda mniej więcej tak:
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
W tej konfiguracji ograniczam FPS wątku renderującego do FPS wątku aktualizacji. Poza tym używam sleep()
do ograniczenia zarówno renderowania, jak i aktualizacji FPS wątku do 60, więc dwie funkcje oczekiwania nie będą długo czekać.
Problemem jest:
Średnie użycie procesora wynosi około 0,1%. Czasami nawet do 25% (w czterordzeniowym komputerze PC). Oznacza to, że wątek czeka na drugi, ponieważ funkcja oczekiwania jest pętlą while z funkcją testowania i ustawiania, a pętla while zużywa wszystkie zasoby procesora.
Moje pierwsze pytanie brzmi: czy istnieje inny sposób synchronizacji dwóch wątków? Zauważyłem, że std::mutex::lock
nie używaj procesora, gdy czeka on na zablokowanie zasobu, więc nie jest to pętla while. Jak to działa? Nie mogę użyć, std::mutex
ponieważ będę musiał zablokować je w jednym wątku i odblokować w innym wątku.
Drugie pytanie brzmi; skoro program działa zawsze z prędkością 60 klatek na sekundę, dlaczego czasami jego użycie procesora skacze do 25%, co oznacza, że jedno z dwóch czekań dużo czeka? (oba wątki są ograniczone do 60 klatek na sekundę, więc idealnie nie będą wymagały dużo synchronizacji).
Edycja: Dzięki za wszystkie odpowiedzi. Najpierw chcę powiedzieć, że nie zaczynam nowego wątku dla każdej ramki do renderowania. Zaczynam zarówno aktualizację, jak i renderowanie na początku. Myślę, że wielowątkowość może zaoszczędzić trochę czasu: Mam następujące funkcje: FastAlg () i Alg (). Alg () to zarówno moja aktualizacja obj, jak i obiekt render, a Fastalg () to moja „kolejka wysyłania renderowania do” renderer ”. W jednym wątku:
Alg() //update
FastAgl()
Alg() //render
W dwóch wątkach:
Alg() //update while Alg() //render last frame
FastAlg()
Więc może wielowątkowość może zaoszczędzić ten sam czas. (w rzeczywistości robi to w prostej aplikacji matematycznej, gdzie alg jest długim algorytmem, a szybszym - szybszym)
Wiem, że sen nie jest dobrym pomysłem, chociaż nigdy nie miałem problemów. Czy to będzie lepsze?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Ale będzie to nieskończona pętla while, która będzie wykorzystywała cały procesor. Czy mogę użyć trybu uśpienia (liczba <15), aby ograniczyć użycie? W ten sposób będzie działać na przykład przy 100 fps, a funkcja aktualizacji zostanie wywołana tylko 60 razy na sekundę.
Aby zsynchronizować dwa wątki, użyję funkcji waitforsingleobject z createSemaphore, aby móc blokować i odblokowywać różne wątki (bez użycia pętli while), prawda?