2011-07-06 2 views
5

मैं ऐसी परिस्थिति में हूं जहां मेरे पास ऐसी गेम ऑब्जेक्ट्स हैं जिनमें वर्चुअल फ़ंक्शन अपडेट() है। बहुत सारी गेम ऑब्जेक्ट्स (वर्तमान में 7000 से थोड़ा अधिक) हैं और लूप कॉल उन सभी के लिए अपडेट (अन्य चीजों के साथ)। मेरे सहयोगी ने सुझाव दिया कि हमें वर्चुअल फ़ंक्शन को पूरी तरह से हटा देना चाहिए। जैसा कि आप कल्पना कर सकते हैं, यह बहुत से रिफैक्टरिंग लेगा।एक तंग लूप में वर्चुअल फ़ंक्शन की लागत

मैंने this answer देखा है लेकिन मेरे मामले में, प्रोफाइलिंग का मतलब है कि मुझे बहुत सारे कोड बदलना है। इसलिए इससे पहले कि मैंने शुरू करने के बारे में भी सोचा था, मैंने सोचा था कि मैं यहां इस राय के लिए पूछूंगा कि इस मामले में रिफैक्टरिंग इसके लायक है या नहीं।

ध्यान दें कि मैंने लूप के अन्य हिस्सों का प्रोफाइल किया है और उन हिस्सों को अनुकूलित करने की कोशिश कर रहा है जो सबसे लंबे समय तक ले रहे हैं। मुझे संदेह है कि इस मामले में वर्चुअल फ़ंक्शन कॉल कुछ है जिसके बारे में मुझे चिंता नहीं करनी चाहिए, लेकिन मैं तब तक सुनिश्चित नहीं हो सकता जब तक कि मैं प्रोफ़ाइल नहीं करता और जब तक मैं कोड बदल नहीं जाता तब तक मैं प्रोफ़ाइल नहीं कर सकता (जो बहुत कुछ है)। यह भी ध्यान रखें कि कुछ अद्यतन फ़ंक्शन बहुत छोटे होते हैं जबकि अन्य अधिक जटिल होते हैं।

EDIT: बहुत से जवाब हैं जो महान अंतर्दृष्टि देते हैं, इसलिए भविष्य में इस प्रश्न पर जो कोई भी ठोकर खाता है, वह सभी उत्तरों पर नज़र डालें, न कि केवल चयनित व्यक्ति।

+2

आपके द्वारा प्रदान की गई जानकारी से, ऐसा लगता है कि यह प्रतिक्रिया करना कठिन या असंभव हो सकता है। कारण यह है कि कई अलग-अलग प्रकार के अपडेट() फ़ंक्शंस हैं। आप सभी को रिफैक्टरिंग द्वारा प्राप्त करने जा रहे हैं कि वर्चुअल फ़ंक्शन कॉल को स्विच-केस या if-statement द्वारा प्रतिस्थापित किया जाएगा, जो प्रदर्शन में बेहतर नहीं हैं। – tp1

+2

ऑप्टिमाइज़ेशन के बारे में कुछ पूछने की हिम्मत कैसे करें! : पी ... सामान्य रूप से, -1 इस प्रकार के प्रश्नों के बिना क्यों समझाए। वैसे भी, उत्तर देने वाले हर किसी के लिए धन्यवाद। मुझे एक और राय के लिए जरूरी था, जो मुझे मिला। निश्चित नहीं है कि क्यों कुछ लोग हर चीज को दफनाने के लिए नरक हैं और कुछ भी है जो 'ऑप्टिमाइज़' – Samaursa

+0

शब्द भी है। मैं अपने स्वयं के गेम इंजन पर काम कर रहा हूं, जो वर्तमान में लाइन मशीन के शीर्ष पर लगभग 10fps पर चलता है। सुनिश्चित नहीं है कि कहां देखना है, लेकिन मुझे पूछने से डर है। मेरे इंजन में मैं दो सूचियों का उपयोग कर रहा हूं, सभी ऑब्जेक्ट्स के लिए एक (जिस तरह से मेरे सिस्टम में लाइव ऑब्जेक्ट्स से अधिक है - टकराव एक ऑब्जेक्ट सक्रिय नहीं करते हैं) और एक लाइव ऑब्जेक्ट्स के लिए। – dascandy

उत्तर

6

यदि आप प्रोफ़ाइल नहीं कर सकते हैं, तो यह देखने के लिए असेंबलर कोड पर एक नज़र डालें कि लुकअप वास्तव में कितना महंगा है। यह एक साधारण अप्रत्यक्ष कूद हो सकता है जो लगभग कुछ भी नहीं लेता है।

यदि आपको रिफैक्टर की आवश्यकता है, तो यहां एक सुझाव दिया गया है: "अद्यतनXxx" कक्षाएं बनाएं जो नई गैर वर्चुअल update() विधि को कॉल करने के बारे में जानें। उनको एक सरणी में एकत्र करें और फिर उन पर update() पर कॉल करें।

लेकिन मेरा अनुमान है कि आप अधिक बचत नहीं करेंगे, खासकर केवल 7 के ऑब्जेक्ट्स के साथ नहीं।

प्रोफाइलिंग पर नोट: यदि आप प्रोफाइलर का उपयोग नहीं कर सकते हैं (मुझे आश्चर्य क्यों है), update() पर कॉल करने के लिए कॉल करें और लॉग इन करें जो 100ms से अधिक समय लेते हैं। समय महंगा नहीं है और यह आपको तुरंत पता लगाने की अनुमति देता है कि कौन सी कॉल सबसे महंगी हैं।हालांकि यह एक ही कोड नहीं है

+0

यह एक बहुत अच्छा सुझाव है। अपने और डस्कंडी के जवाब को ध्यान में रखते हुए, मैं इसके बारे में अभी भूल जाऊंगा लेकिन मेरे खाली समय में आपका सुझाव एक शॉट देगा और देखें कि क्या होता है (+1) – Samaursa

10

एक वर्चुअल फ़ंक्शन कॉल एक एकल संकेत और हार्ड-टू-अनुमानित कूद से अधिक जोड़ने वाला नहीं है। इसका मतलब है कि आम तौर पर आप एक पाइपलाइन फ्लश या प्रति वर्चुअल फ़ंक्शन के बारे में 20 चक्र नीचे होते हैं। उनमें से 7000 लगभग 140000 चक्र हैं, जो आपके औसत अद्यतन फ़ंक्शन की तुलना में नगण्य होना चाहिए। यदि ऐसा नहीं है, तो कहें कि आपके अधिकांश अपडेट फ़ंक्शंस खाली हैं, आप इस उद्देश्य के लिए अपडेट-सक्षम ऑब्जेक्ट्स को एक अलग सूची में डालने पर विचार कर सकते हैं।

आभासी फ़ंक्शन को हटाने से आप में से एक को एक समान लेकिन स्वयं-लागू प्रणाली के साथ बदलना होगा। यह सही जगह है जहां वर्चुअल फ़ंक्शन समझ में आता है।

प्रति संदर्भ, 140000 चक्र लगभग 50 माइक्रोसॉंड हैं। यह एक विशाल पाइपलाइन के साथ पी 4 मान रहा है और हमेशा एक पूर्ण पाइपलाइन फ्लश (जिसे आप आमतौर पर प्राप्त नहीं करते हैं)।

+0

उत्कृष्ट, यह निश्चित रूप से मेरे निर्णय में मदद करेगा, धन्यवाद (+1) – Samaursa

1

आभासी, इनलाइन और प्रत्यक्ष कॉल के साथ एक और परीक्षण आप यहाँ पा सकते हैं [कड़ी यहाँ विवरण दर्ज] [1] Virtual functions and performance - C++

8

और आप कर रहे हैं के रूप में ही संकलक नहीं हो सकता है का उपयोग करते हुए, यहाँ एक नहीं बल्कि पुराने बेंचमार्क (बेंच ++ जो Orost द्वारा) से संदर्भ डेटा का एक सा है:

Test Name: F000005       Class Name: Style 
CPU Time:  7.70 nanoseconds   plus or minus  0.385 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way if/else if statement 
compare this test with F000006 


Test Name: F000006       Class Name: Style 
CPU Time:  2.00 nanoseconds   plus or minus  0.0999 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way switch statement 
compare this test with F000005 


Test Name: F000007       Class Name: Style 
CPU Time:  3.41 nanoseconds   plus or minus  0.171 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way sparse switch statement 
compare this test with F000005 and F000006 


Test Name: F000008       Class Name: Style 
CPU Time:  2.20 nanoseconds   plus or minus  0.110 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way virtual function class 
compare this test with F000006 

यह विशेष रूप से परिणाम कुलपति ++ 9.0 (वी.एस. 2008) के 64-बिट संस्करण के साथ संकलन से है, लेकिन यह काफी है मैंने हाल ही के अन्य कंपाइलर्स से जो देखा है उसके समान। निचली पंक्ति यह है कि वर्चुअल फ़ंक्शन अधिकांश स्पष्ट विकल्पों की तुलना में तेज़ है, और बहुत उसी गति के करीब है जो इसे मारता है (वास्तव में, दोनों बराबर बराबर त्रुटि के मार्जिन के भीतर होता है)। हालांकि, यह घने होने वाले मूल्यों पर निर्भर करता है - जैसा कि आप F00007 में देख सकते हैं, यदि मान स्पैस हैं, तो स्विच स्टेटमेंट वर्चुअल फ़ंक्शन कॉल से धीमा कोड उत्पन्न करता है।

नीचे पंक्ति: वर्चुअल फ़ंक्शन कॉल शायद देखने के लिए गलत जगह है। रिफैक्टर कोड आसानी से धीमा हो सकता है, और यहां तक ​​कि सबसे अच्छा यह संभवतः नोटिस या देखभाल करने के लिए पर्याप्त नहीं होगा।

+0

वाह, उत्कृष्ट, ऐसा करने के लिए समय लेने के लिए धन्यवाद। यह इसके बारे में चिंता करने के मेरे निर्णय को दृढ़ करता है (+1) – Samaursa

+0

+1 बाद के विचार के रूप में: सी ++ कुछ सालों से आसपास रहा है और यह आश्चर्य की बात नहीं है कि हार्डवेयर डेवलपर्स ने सीपीयू बनाने शुरू कर दिए हैं जो इसे कुशलतापूर्वक चला सकते हैं। :-) –

+0

@ जेरी: क्या आप किसी भी मौके से स्रोत को लिंक प्रदान कर सकते हैं? मुझे बेंच ++ – Samaursa