मैं एक साधारण 2 डी गेम इंजन बना रहा हूं और यह जानने के लिए कि यह कैसे किया जाता है, अलग-अलग थ्रेड्स में स्प्राइट्स को अपडेट और रेंडर करना चाहता हूं।
मुझे अपडेट थ्रेड को सिंक्रनाइज़ करने और एक रेंडर करने की आवश्यकता है। वर्तमान में, मैं दो परमाणु झंडे का उपयोग करता हूं। वर्कफ़्लो कुछ इस तरह दिखता है:
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
इस सेटअप में मैं रेंडर थ्रेड के एफपीएस को अपडेट थ्रेड के एफपीएस तक सीमित करता हूं। इसके अलावा, मैं sleep()
थ्रेड के FPS को 60 तक रेंडर और अपडेट करने, दोनों को सीमित करने के लिए उपयोग करता हूं , इसलिए दोनों प्रतीक्षा फ़ंक्शन बहुत समय तक इंतजार नहीं करेंगे।
यह समस्या है:
औसत CPU उपयोग लगभग 0.1% है। कभी-कभी यह 25% (एक क्वाड कोर पीसी में) तक जाता है। इसका मतलब है कि एक थ्रेड दूसरे की प्रतीक्षा कर रहा है क्योंकि प्रतीक्षा फ़ंक्शन एक परीक्षण और सेट फ़ंक्शन के साथ एक लूप है, और थोड़ी देर लूप आपके सभी सीपीयू संसाधनों का उपयोग करेगा।
मेरा पहला सवाल है: क्या दो धागों को समेटने का एक और तरीका है? मैंने देखा कि std::mutex::lock
सीपीयू का उपयोग न करें जबकि यह एक संसाधन को लॉक करने के लिए इंतजार कर रहा है, इसलिए यह थोड़ी देर का लूप नहीं है। यह कैसे काम करता है? मैं उपयोग नहीं कर सकता std::mutex
क्योंकि मुझे उन्हें एक धागे में बंद करना होगा और दूसरे धागे में अनलॉक करना होगा।
दूसरा प्रश्न है; चूंकि कार्यक्रम हमेशा 60 एफपीएस पर चलता है, इसलिए कभी-कभी इसका सीपीयू उपयोग 25% तक हो जाता है, जिसका अर्थ है कि दोनों में से एक प्रतीक्षा बहुत इंतजार कर रही है? (दो धागे दोनों 60fps तक सीमित हैं, इसलिए उन्हें आदर्श रूप से बहुत अधिक सिंक्रनाइज़ेशन की आवश्यकता नहीं होगी)।
संपादित करें: सभी उत्तरों के लिए धन्यवाद। पहले मैं कहना चाहता हूं कि मैं रेंडर के लिए एक नया धागा शुरू नहीं करता हूं। मैं शुरू में अद्यतन और रेंडर लूप दोनों शुरू करता हूं। मुझे लगता है कि मल्टीथ्रेडिंग कुछ समय बचा सकता है: मेरे पास निम्नलिखित कार्य हैं: FastAlg () और Alg ()। Alg () मेरे अपडेट ओब्जेक्ट और रेंडर ऑबज दोनों हैं और Fastalg () मेरा "रेंडर रेंडर टू" रेंडर "है। एक ही धागे में:
Alg() //update
FastAgl()
Alg() //render
दो धागे में:
Alg() //update while Alg() //render last frame
FastAlg()
तो शायद मल्टीथ्रेडिंग उसी समय को बचा सकता है। (वास्तव में एक साधारण गणित अनुप्रयोग में यह होता है, जहाँ alg एक लंबी एल्गोरिथ्म है जो फास्टैग को तेजी से बढ़ाता है)
मुझे पता है कि नींद एक अच्छा विचार नहीं है, हालांकि मुझे कभी समस्या नहीं होती है। क्या यह बेहतर होगा?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
लेकिन यह एक अनंत होगा जब लूप सभी सीपीयू का उपयोग करेगा। क्या मैं उपयोग को सीमित करने के लिए नींद (एक संख्या <15) का उपयोग कर सकता हूं? इस तरह से, यह उदाहरण के लिए, 100 एफपीएस पर चलेगा, और अपडेट फ़ंक्शन को प्रति सेकंड सिर्फ 60 बार कहा जाएगा।
दो थ्रेड्स को सिंक्रनाइज़ करने के लिए मैं createSemaphore के साथ waforsingleobject का उपयोग करूंगा ताकि मैं अलग-अलग थ्रेड में लॉक और अनलॉक कर सकूं (कुछ समय बाद लूप का उपयोग करके व्हाइटआउट), क्या मैं नहीं करूंगा?