Saya membuat mesin permainan 2D sederhana dan saya ingin memperbarui dan membuat sprite di utas yang berbeda, untuk mempelajari bagaimana hal itu dilakukan.
Saya perlu menyinkronkan utas pembaruan dan render. Saat ini, saya menggunakan dua bendera atom. Alur kerjanya terlihat seperti:
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
Dalam pengaturan ini saya membatasi FPS utas render ke FPS utas pembaruan. Selain itu saya gunakan sleep()
untuk membatasi render dan memperbarui FPS utas hingga 60, jadi dua fungsi menunggu tidak akan menunggu banyak waktu.
Masalahnya adalah:
Penggunaan CPU rata-rata sekitar 0,1%. Kadang-kadang naik hingga 25% (dalam quad core PC). Ini berarti bahwa utas sedang menunggu yang lain karena fungsi tunggu adalah loop sementara dengan fungsi tes dan set, dan loop sementara akan menggunakan semua sumber daya CPU Anda.
Pertanyaan pertama saya adalah: apakah ada cara lain untuk menyinkronkan kedua utas? Saya perhatikan bahwa std::mutex::lock
jangan gunakan CPU saat sedang menunggu untuk mengunci sumber daya sehingga tidak loop sementara. Bagaimana cara kerjanya? Saya tidak dapat menggunakan std::mutex
karena saya harus mengunci mereka di satu utas dan membuka kunci di utas lainnya.
Pertanyaan lainnya adalah; karena program selalu berjalan pada 60 FPS mengapa terkadang penggunaan CPU-nya melonjak hingga 25%, artinya salah satu dari keduanya menunggu banyak? (kedua utas keduanya terbatas pada 60fps sehingga idealnya tidak perlu banyak sinkronisasi).
Sunting: Terima kasih atas semua balasan. Pertama saya ingin mengatakan saya tidak memulai utas baru setiap frame untuk di-render. Saya memulai pembaruan dan render loop di awal. Saya pikir multithreading dapat menghemat waktu: Saya memiliki fungsi-fungsi berikut: FastAlg () dan Alg (). Alg () adalah kedua saya Perbarui obj dan render obj dan Fastalg () adalah "kirim antrian render ke" renderer "". Dalam satu utas:
Alg() //update
FastAgl()
Alg() //render
Dalam dua utas:
Alg() //update while Alg() //render last frame
FastAlg()
Jadi mungkin multithreading dapat menghemat waktu yang sama. (sebenarnya dalam aplikasi matematika sederhana yang dilakukannya, di mana alg adalah algoritma yang panjang dan yang lebih cepat)
Saya tahu bahwa tidur bukanlah ide yang baik, meskipun saya tidak pernah memiliki masalah. Apakah ini akan lebih baik?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
Tapi ini akan menjadi loop sementara yang akan menggunakan semua CPU. Bisakah saya menggunakan sleep (angka <15) untuk membatasi penggunaan? Dengan cara ini ia akan berjalan pada, misalnya, 100 fps, dan fungsi pembaruan akan dipanggil hanya 60 kali per detik.
Untuk menyinkronkan dua utas, saya akan menggunakan waitforsingleobject dengan createSemaphore jadi saya akan dapat mengunci dan membuka kunci di utas yang berbeda (tidak menggunakan perulangan sementara), bukan?