2012-01-01 22 views
6

मुझे सर्वर साइड गेम लूप बनाने की आवश्यकता है, समस्या यह है कि लूप सीपीयू उपयोग को सीमित कैसे करें।करता है जबकि लूप हमेशा पूर्ण CPU उपयोग लेता है?

प्रोग्रामिंग के अपने अनुभव में, व्यस्त लूप हमेशा अधिकतम CPU उपयोग ले सकता है। लेकिन मैं एसडीएल (सरल डायरेक्टमीडिया लेयर) का कोड पढ़ रहा हूं, इसमें एक फंक्शन SDL_Delay(UINT32 ms) है, और इसमें थोड़ी देर लूप है, क्या यह अधिकतम सीपीयू उपयोग लेता है, अगर नहीं, तो क्यों?

https://github.com/eddieringle/SDL/blob/master/src/timer/unix/SDL_systimer.c#L137-158

do { 
    errno = 0; 

#if HAVE_NANOSLEEP 
    tv.tv_sec = elapsed.tv_sec; 
    tv.tv_nsec = elapsed.tv_nsec; 
    was_error = nanosleep(&tv, &elapsed); 
#else 
    /* Calculate the time interval left (in case of interrupt) */ 
    now = SDL_GetTicks(); 
    elapsed = (now - then); 
    then = now; 
    if (elapsed >= ms) { 
     break; 
    } 
    ms -= elapsed; 
    tv.tv_sec = ms/1000; 
    tv.tv_usec = (ms % 1000) * 1000; 

    was_error = select(0, NULL, NULL, NULL, &tv); 
#endif /* HAVE_NANOSLEEP */ 
} while (was_error && (errno == EINTR)); 

उत्तर

3

इस कोड को एक टाइमआउट के लिए select उपयोग करता है। select आमतौर पर एक फ़ाइल डिस्क्रिप्टर लेता है, और कॉलर प्रतीक्षा करता है जब तक कि एक आईओ घटना एफडी पर नहीं होती है। यह प्रतीक्षा करने के लिए अधिकतम समय के लिए एक टाइमआउट तर्क भी लेता है। यहां एफडी 0 है, इसलिए कोई घटना नहीं होगी, और टाइमआउट पहुंचने पर फ़ंक्शन हमेशा वापस आ जाएगा।

select(3) कि आप सी पुस्तकालय से प्राप्त select(2) सिस्टम कॉल है, जो फोन करने का मतलब है select(3) अंततः कर्नेल में आप हो जाता है चारों ओर एक आवरण है। कर्नेल तब प्रक्रिया को शेड्यूल नहीं करता जब तक कोई आईओ ईवेंट नहीं होता है, या टाइमआउट पहुंच जाता है। इसलिए प्रतीक्षा करते समय प्रक्रिया सीपीयू का उपयोग नहीं कर रही है।

जाहिर है, कर्नेल और प्रक्रिया शेड्यूलिंग में कूद विलंब पेश करता है। तो यदि आपके पास बहुत कम विलंबता (नैनोसेकंड) होनी चाहिए तो आपको व्यस्त प्रतीक्षा का उपयोग करना चाहिए।

+2

यदि कोई 'सिलेक्ट' सिग्नल सिग्नल प्राप्त करता है, तो यह 'errno == EINTR' के साथ -1 देता है, इसलिए यह सच नहीं है कि' चयन 'हमेशा पूछे जाने वाले समय को सोता है। –

+0

ठीक है, मेरी गलती। कोई विचार क्यों जीएनयू मैनुअल इस मामले में नींद का चयन करने की सिफारिश कर रहा है? –

+0

क्योंकि कुछ पुराने (गैर लिनक्स) यूनिक्स सिस्टम 'नींद' को 'सिगलआरएम' और 'पॉज़' के साथ लागू किया गया था –

3

कि पाश सभी सीपीयू नहीं ले जाएगा। यह दो विभिन्न कार्यों के लिए समय की एक निश्चित राशि और दे एक और धागा सीपीयू उपयोग के लिए धागा रोकने के लिए ऑपरेटिंग सिस्टम को बताने के लिए में से एक का इस्तेमाल करता है:

// First function call - if HAVE_NANOSLEEP is defined. 
was_error = nanosleep(&tv, &elapsed); 

// Second function call - fallback without nanosleep. 
was_error = select(0, NULL, NULL, NULL, &tv); 
+0

क्यों? केवल एक 'जबकि (1);' यह पूर्ण सीपीयू उपयोग करेगा, लेकिन यह –

+0

'नैनोस्लीप 'और' चयन '(जैसा कि आपके नमूने में कहा जाता है) वापस लौटने से पहले दिए गए समय के लिए अवरुद्ध होगा। जबकि लूप केवल एक विशेष मामले को संभालने के लिए है जहां नींद का कार्य बाधित होता है और बहुत जल्दी लौटाता है। –

+0

आपका मतलब धागा है, लेकिन केवल एक धागा के बारे में कैसे? –

1

जबकि एसडीएल_Delay में थ्रेड अवरुद्ध है, यह CPU को अन्य कार्यों में उत्पन्न करता है। यदि देरी काफी लंबी है, तो ऑपरेटिंग सिस्टम सीपीयू को निष्क्रिय या रोक मोड में रखेगा यदि कोई अन्य काम नहीं है। ध्यान दें कि यदि देरी का समय कम से कम 20 मिलीसेकंड नहीं है तो यह ठीक से काम नहीं करेगा।

हालांकि, यह आमतौर पर ऐसा करने का सही तरीका नहीं है जिसे आप करने की कोशिश कर रहे हैं। आपकी बाहरी समस्या क्या है? आपका गेम लूप कभी भी ऐसा नहीं कर रहा है जो इस समय किया जाना चाहिए और फिर कुछ ऐसा होने की प्रतीक्षा करनी चाहिए ताकि उसके पास और अधिक काम हो सके? तत्काल करने के लिए हमेशा असीमित काम कैसे हो सकता है?

संबंधित मुद्दे