Basit bir 2D oyun motoru oluşturuyorum ve nasıl yapıldığını öğrenmek için spriteları farklı iş parçacıklarında güncellemek ve oluşturmak istiyorum.
Güncelleme iş parçacığı ve render bir senkronize etmek gerekiyor. Şu anda iki atom bayrağı kullanıyorum. İş akışı şuna benzer:
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
Bu kurulumda, render iş parçacığının FPS'sini güncelleme iş parçacığının FPS'si ile sınırlandırıyorum. Ayrıca, işleme sleep()
ve güncelleme iş parçacığının FPS'sini 60 ile sınırlamak için kullanıyorum , böylece iki bekleme işlevi çok fazla beklemeyecek.
Problem şu:
Ortalama CPU kullanımı yaklaşık% 0.1'dir. Bazen% 25'e kadar çıkar (dört çekirdekli bir bilgisayarda). Bu, bir iş parçacığının diğerini beklediği anlamına gelir, çünkü wait işlevi bir test ve set işlevine sahip bir while döngüsüdür ve while döngüsü tüm CPU kaynaklarınızı kullanır.
İlk sorum şu: İki iş parçacığını senkronize etmenin başka bir yolu var mı? std::mutex::lock
Bir kaynak kilitlemek için beklerken CPU'yu kullanmadığımı fark ettim, bu yüzden bir süre döngüsü değil. O nasıl çalışır? Kullanamıyorum std::mutex
çünkü bir iş parçacığında onları kilitlemek ve başka bir iş parçacığında kilidini açmak gerekir.
Diğer soru; program her zaman 60 FPS'de çalıştığı için neden bazen CPU kullanımı% 25'e atlıyor, yani iki beklemeden biri çok şey bekliyor? (her iki iş parçacığı da 60 fps ile sınırlıdır, bu nedenle ideal olarak çok fazla senkronizasyona ihtiyaç duymazlar).
Edit: Tüm cevaplar için teşekkürler. Öncelikle her çerçeve için yeni bir iş parçacığı oluşturmadığımı söylemek istiyorum. Başlangıçta hem güncelleme hem de oluşturma döngüsünü başlatıyorum. Multithreading biraz zaman kazandırabilir düşünüyorum: Aşağıdaki işlevleri var: FastAlg () ve Alg (). Alg () benim Güncelleme obj ve render obj ve Fastalg () "renderer" için "render sırası". Tek bir iş parçacığında:
Alg() //update
FastAgl()
Alg() //render
İki iş parçacığında:
Alg() //update while Alg() //render last frame
FastAlg()
Yani belki çoklu iş parçacığı aynı zamandan tasarruf edebilir. (aslında, alg'in uzun bir algoritma olduğu ve daha hızlı bir algoritma olduğu basit bir matematik uygulamasında)
Asla sorun yaşamamama rağmen uykunun iyi bir fikir olmadığını biliyorum. Bu daha iyi olacak mı?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Ancak bu, tüm CPU'yu kullanacak sonsuz bir döngü olacaktır. Kullanımı sınırlamak için uyku (<15) sayısı kullanabilir miyim? Bu şekilde, örneğin 100 fps hızında çalışır ve güncelleme işlevi saniyede sadece 60 kez çağrılır.
İki iş parçacığı senkronize etmek için waitforsingleobject ile createSemaphore kullanacağım, böylece farklı iş parçacığında (while döngüsü kullanarak whitout) kilitleyip kilidini açabiliyorum, değil mi?