मेरे कोड के धारावाहिक प्रदर्शन में सुधार के लिए कुछ अच्छी रणनीतियाँ क्या हैं?


66

मैं कम्प्यूटेशनल विज्ञान में काम करता हूं, और इसके परिणामस्वरूप, मैं अपने समय की एक गैर-तुच्छ राशि खर्च करता हूं जो कई कोड के वैज्ञानिक प्रवाह को बढ़ाने की कोशिश कर रहा है, साथ ही साथ इन कोड की दक्षता को भी समझता है।

आइए मान लें कि मैंने जिस सॉफ्टवेयर पर काम कर रहा हूं, उसके बनाम प्रदर्शन / पठनीयता / पुन: प्रयोज्यता / अनुरक्षण व्यापार का मूल्यांकन किया है, और मैंने फैसला किया है कि प्रदर्शन के लिए जाने का समय है। आइए यह भी मान लें कि मुझे पता है कि मेरी समस्या (फ्लॉप / एस और मेमोरी बैंडविड्थ के संदर्भ में) के लिए बेहतर एल्गोरिदम नहीं है। आप यह भी मान सकते हैं कि मेरा कोड आधार C, C ++, या फोरट्रान जैसी निम्न-स्तरीय भाषा में है। अंत में, मान लेते हैं कि कोड में कोई समानता नहीं है, या कि हम केवल एक ही कोर पर प्रदर्शन में रुचि रखते हैं।

पहले प्रयास करने के लिए सबसे महत्वपूर्ण चीजें क्या हैं? मुझे कैसे पता चलेगा कि मुझे कितना प्रदर्शन मिल सकता है?

जवाबों:


66

सबसे पहले, जैसा कि कौशल और डैन ने बताया है, प्रोफाइलिंग आवश्यक है। मैं व्यक्तिगत रूप से लिनक्स पर इंटेल के वीटीएन एम्पलीफायर का उपयोग करता हूं क्योंकि यह मुझे एक बहुत ही बारीक-बारीक अवलोकन देता है जहां समय क्या कर रहा था।

यदि आप एल्गोरिथ्म को बदलने नहीं जा रहे हैं (अर्थात यदि कोई बड़ा परिवर्तन नहीं होगा जो आपकी सभी आशाओं को अप्रचलित कर देगा), तो मैं कुछ सामान्य कार्यान्वयन विवरणों की तलाश करना चाहूंगा जो एक बड़ा बदलाव ला सकते हैं:

  • मेमोरी लोकेलिटी : वह डेटा है जिसे एक साथ पढ़ा / उपयोग किया जाता है, एक साथ संग्रहीत भी किया जाता है, या आप बिट्स और टुकड़ों को यहां और वहां उठा रहे हैं?

  • मेमोरी संरेखण : क्या आपके युगल वास्तव में 4 बाइट्स से संरेखित हैं? आपने अपना पैक कैसे बनाया structs? पांडित्यपूर्ण होने के लिए, posix_memalignइसके बजाय का उपयोग करें malloc

  • कैश दक्षता : स्थानीयता अधिकांश कैश दक्षता मुद्दों का ध्यान रखती है, लेकिन अगर आपके पास कुछ छोटी डेटा संरचनाएं हैं जिन्हें आप अक्सर पढ़ते / लिखते हैं, तो यह मदद करता है कि वे एक कैश लाइन के कई या एक पूर्णांक (आमतौर पर 64 बाइट्स) हैं। यदि आपका डेटा कैशे लाइन के आकार के साथ संरेखित है, तो भी यह मदद करता है। यह डेटा के एक टुकड़े को लोड करने के लिए आवश्यक रीड की संख्या को काफी कम कर सकता है।

  • वैश्वीकरण : नहीं, हाथ से कोडित कोडांतरक के साथ मानसिक मत जाओ। gccवेक्टर प्रकार प्रदान करता है जो SSE / AltiVec / जो भी निर्देश स्वचालित रूप से अनुवादित होते हैं।

  • निर्देश-स्तर समानता : वैश्वीकरण का हरामी बेटा। यदि कुछ अक्सर दोहराए जाने वाले गणना अच्छी तरह से सदिश नहीं करते हैं, तो आप इनपुट मानों को संचय करने की कोशिश कर सकते हैं और एक बार में कई मानों की गणना कर सकते हैं। यह एक तरह से लूप की तरह है। यहां आप जो शोषण कर रहे हैं वह यह है कि आपके सीपीयू में आमतौर पर प्रति कोर एक से अधिक फ्लोटिंग-पॉइंट यूनिट होंगे।

  • अंकगणितीय परिशुद्धता : क्या आपको वास्तव में आपके द्वारा किए जाने वाले हर चीज में डबल-सटीक अंकगणित की आवश्यकता है? उदाहरण के लिए, यदि आप न्यूटन के पुनरावृत्ति में सुधार की गणना कर रहे हैं, तो आपको आमतौर पर उन सभी अंकों की आवश्यकता नहीं है, जिनकी आप गणना कर रहे हैं। अधिक गहन चर्चा के लिए, इस पेपर को देखें ।

daxpy_cvec इस धागे में इनमें से कुछ तरकीबों का इस्तेमाल किया जाता है । यह कहने के बाद कि, यदि आप फोरट्रान का उपयोग कर रहे हैं (मेरी पुस्तकों में निम्न-स्तरीय भाषा नहीं), तो आपका इन "ट्रिक्स" पर बहुत कम नियंत्रण होगा।

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

अपडेट करें

जब से मैंने यह लिखा है, तब से कुछ समय हो गया है और मैंने ध्यान नहीं दिया कि यह इतना लोकप्रिय उत्तर बन गया था। इस कारण से, मैं एक महत्वपूर्ण बिंदु जोड़ना चाहूंगा:

  • अपने स्थानीय कंप्यूटर साइंटिस्ट से बात करें : क्या यह अच्छा नहीं होगा यदि कोई ऐसा अनुशासन हो जो विशेष रूप से एल्गोरिदम बनाने और / या कम्प्यूटेशन को अधिक कुशल / सुरुचिपूर्ण / समानांतर बनाने के साथ निपटा हो, और हम सभी उनसे सलाह के लिए जा सकते हैं? खैर, अच्छी खबर यह है कि अनुशासन मौजूद है: कंप्यूटर विज्ञान। संभावना है, आपकी संस्था के पास एक पूरा विभाग भी है। इन लोगों से बात करो।

मुझे यकीन है कि कई गैर-कंप्यूटर वैज्ञानिकों के लिए यह निराश करने वाली चर्चाओं की यादें वापस लाएगा, जिन्होंने कहा कि अनुशासन से कुछ भी नहीं हुआ, या अन्य लोगों के यादों के साथ। निराश मत होना। अंतःविषय सहयोग एक मुश्किल काम है, और यह थोड़ा काम करता है, लेकिन पुरस्कार बड़े पैमाने पर हो सकते हैं।

मेरे अनुभव में, एक कंप्यूटर वैज्ञानिक (सीएस) के रूप में, चाल उम्मीदों और संचार दोनों को सही पाने में है।

उम्मीद- समझदारी, एक सीएस केवल आपकी मदद करेगा यदि वह समझता है कि आपकी समस्या दिलचस्प है। यह बहुत ज्यादा आपके द्वारा लिखे गए कोड के एक टुकड़े को अनुकूलित / सदिश / अनुकूलित करने की कोशिश को शामिल नहीं करता है, लेकिन वास्तव में टिप्पणी नहीं की गई है, एक समस्या के लिए यह समझ में नहीं आता है। सीएस आमतौर पर अंतर्निहित समस्या में अधिक रुचि रखते हैं, जैसे कि इसे हल करने के लिए उपयोग किए जाने वाले एल्गोरिदम। उन्हें अपना समाधान मत दो , उन्हें अपनी समस्या दो

इसके अलावा, सीएस को " यह समस्या पहले ही हल हो गई है " कहने के लिए तैयार रहें , और बस आपको एक पेपर का संदर्भ दें। सलाह का एक शब्द: उस कागज को पढ़ें और, अगर यह वास्तव में आपकी समस्या पर लागू होता है, तो जो भी एल्गोरिदम सुझाता है उसे लागू करें। यह एक सीएस नहीं है जो स्मॉग है, यह एक सीएस है जिसने सिर्फ आपकी मदद की है। नाराज मत हो, याद रखें: यदि समस्या कम्प्यूटेशनल रूप से दिलचस्प नहीं है, अर्थात यह पहले से ही हल हो गया है और समाधान को इष्टतम दिखाया गया है, तो वे इस पर काम नहीं करेंगे, यह आपके लिए बहुत कम कोड है।

संचार वार, याद रखें कि सबसे सीएसएस अपने क्षेत्र में विशेषज्ञ नहीं हैं, और के मामले में समस्या की व्याख्या क्या के रूप में करने का विरोध किया है, तो आप क्या कर रहे हैं कि कैसे और क्यों । हम आमतौर पर क्यों , और कैसे है के बारे में परवाह नहीं है, ठीक है, हम सबसे अच्छा क्या करते हैं।

उदाहरण के लिए, मैं वर्तमान में SPH और Multipoles के आधार पर अपने सिमुलेशन कोड का एक बेहतर संस्करण लिखने पर कम्प्यूटेशनल कॉस्मोलॉजिस्ट के एक समूह के साथ काम कर रहा हूं । डार्क मैटर और गैलेक्सी हेलो (हुह?) के संदर्भ में बात करना बंद करने और गणना के मूल को नीचे करने के लिए तीन बैठकें हुईं , यानी उन्हें प्रत्येक कण के दिए गए त्रिज्या के भीतर सभी पड़ोसियों को खोजने की जरूरत है, उनके ऊपर मात्रा, और फिर सभी उक्त पड़ोसियों पर फिर से चलाएं और उस मात्रा को किसी अन्य संगणना में लागू करें। फिर कणों को स्थानांतरित करें, या कम से कम उनमें से कुछ, और यह सब फिर से करें। आप देखते हैं, जबकि पूर्व अविश्वसनीय रूप से दिलचस्प हो सकता है (यह है!), बाद वाला वह है जो मुझे एल्गोरिदम के बारे में सोचना शुरू करने के लिए समझने की आवश्यकता है।

लेकिन मैं मुख्य बिंदु से विचलित हो रहा हूं: यदि आप वास्तव में अपनी गणना को तेज बनाने में रुचि रखते हैं, और आप खुद एक कंप्यूटर वैज्ञानिक नहीं हैं, तो एक पर बात करें।


4
प्रोफाइलिंग उपकरण के रूप में, मैं वेलग्रिंड के बारे में नहीं भूलूंगा
GertVdE

1
मैं आपसे सहमत हूं पेड्रो, जब प्रोग्राम को अनुकूलित किया जा रहा है तो एफ 1 रेस कार की तरह है, जो पहले से ही इष्टतम है। अभ्यास, वैज्ञानिक और नहीं में जो कार्यक्रम मैं देख रहा हूं, वे अक्सर कैडिलैक कूप डेविल्स की तरह हैं। वास्तविक प्रदर्शन प्राप्त करने के लिए, वसा के टन को दूर किया जा सकता है। उसके बाद, चक्र-शेविंग अपने स्ट्राइड को हिट करना शुरू कर देता है।
माइक डनलैवी

1
@ मायिक डनलैवी: पूरी तरह से सहमत हैं। मैंने अपने उत्तर में अधिक एल्गोरिदम से संबंधित मुद्दों को संबोधित करने के लिए एक अपडेट जोड़ा है।
पेड्रो

1
@MikeDunlavey, मैं कर रहा हूँ सीएस लोक :)
पेड्रो

2
मैंने यू मास में एक वार्ता में यह प्रदर्शित किया। यह एक लाइव डेमो था, जिसमें 730x स्पीडअप के सभी चरणों को दिखाया गया था। मुझे लगता है कि एक प्रोफेसर को आधा दर्जन में से एक अंक मिला।
माइक डनलैवी

38

वैज्ञानिक सॉफ्टवेयर अन्य सॉफ्टवेयर से उतना अलग नहीं है, जितना कि यह जानने के लिए कि ट्यूनिंग की आवश्यकता क्या है।

मेरे द्वारा उपयोग की जाने वाली विधि यादृच्छिक ठहराव है । यहाँ कुछ स्पीडअप के बारे में बताया गया है:

यदि समय का एक बड़ा हिस्सा जैसे कार्यों में खर्च किया जाता है logऔर exp, मैं देख सकता हूं कि उन कार्यों के तर्क क्या हैं, उन बिंदुओं के एक समारोह के रूप में, जिनसे उन्हें बुलाया जा रहा है। अक्सर उन्हें एक ही तर्क के साथ बार-बार बुलाया जा रहा है। यदि हां, तो याद रखना एक बड़े पैमाने पर स्पीडअप कारक पैदा करता है।

अगर मैं BLAS या LAPACK फ़ंक्शंस का उपयोग कर रहा हूं, तो मुझे पता चल सकता है कि सरणियों की प्रतिलिपि बनाने के लिए रूटीन का एक बड़ा हिस्सा खर्च किया जाता है, मैट्रिस, चोल्स्की ट्रांसफॉर्म आदि को गुणा किया जाता है।

  • सरणियों की प्रतिलिपि बनाने की दिनचर्या गति के लिए नहीं है, यह सुविधा के लिए है। आप पा सकते हैं कि यह करने के लिए एक कम सुविधाजनक, लेकिन तेज़ तरीका है।

  • मेट्रिसेस को गुणा या उल्टा करने के लिए रूटीन लें या चोल्स्की ट्रांसफ़ॉर्म लें, ऊपरी या निचले त्रिकोण के लिए 'यू' या 'एल' जैसे विकल्प निर्दिष्ट करने वाले वर्ण तर्क हैं। फिर, सुविधा के लिए वहाँ हैं। मुझे जो मिला था, चूंकि मेरे मैट्रिस बहुत बड़े नहीं थे, इसलिए रूटीन आधे से अधिक समय बिता रहे थे और पात्रों की तुलना करने के लिए सबरूटिन को कॉल करने के लिए सिर्फ विकल्पों को समझने के लिए। सबसे महंगी गणित दिनचर्या के विशेष उद्देश्य के संस्करणों को लिखने से बड़े पैमाने पर स्पीडअप का उत्पादन हुआ।

अगर मैं बाद में विस्तार कर सकता हूं: मैट्रिक्स-मल्टीप्ल रूटीन डीजीईएमएम अपने चरित्र तर्कों को डिकोड करने के लिए एलएसएएमई कहता है। समावेशी प्रतिशत समय (केवल देखने योग्य) को "अच्छे" के रूप में माना जाने वाला प्रोफाइलर कुल मिलाकर, कुल प्रतिशत के कुछ प्रतिशत का उपयोग करके DGEMM दिखा सकता है, जैसे कि 80%, और LSAME कुल समय के कुछ प्रतिशत का उपयोग करके, 50% की तरह। पूर्व को देखते हुए, आपको यह कहने के लिए लुभाया जाएगा कि "अच्छी तरह से इसे भारी रूप से अनुकूलित किया जाना चाहिए, इसलिए मैं इस बारे में बहुत कुछ नहीं कर सकता"। उत्तरार्द्ध को देखते हुए, आपको यह कहने के लिए लुभाया जाएगा "हुह? यह सब क्या है? यह सिर्फ एक छोटी सी दिनचर्या है। यह प्रोफाइलर गलत होना चाहिए!"

यह गलत नहीं है, यह आपको वह नहीं बता रहा है जो आपको जानना चाहिए। क्या यादृच्छिक रोक आपको दिखाता है कि DGEMM स्टैक नमूनों के 80% पर है, और LSAME 50% पर है। (आपको पता लगाने के लिए बहुत सारे नमूनों की आवश्यकता नहीं है। 10 आमतौर पर बहुत सारे हैं।) उन नमूनों में से कई पर अधिक क्या है, DGEMM कोड के कुछ अलग लाइनों से LSAME को कॉल करने की प्रक्रिया में है

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

यह मानना ​​आसान है कि गणित लाइब्रेरी रूटीन को एनटीएच डिग्री के लिए अनुकूलित किया गया है, लेकिन वास्तव में वे उद्देश्यों की एक विस्तृत श्रृंखला के लिए उपयोग करने योग्य हैं। आपको यह देखने की ज़रूरत है कि वास्तव में क्या चल रहा है, न कि यह मान लेना आसान है।

जोड़ा: तो अपने पिछले दो सवालों के जवाब देने के लिए:

पहले प्रयास करने के लिए सबसे महत्वपूर्ण चीजें क्या हैं?

10-20 स्टैक नमूने लें, और उन्हें केवल संक्षेप में न बताएं, समझें कि प्रत्येक आपको क्या बता रहा है। इसे पहले, अंतिम और बीच में करें। (कोई "कोशिश" नहीं है, युवा स्काईवॉकर।)

मुझे कैसे पता चलेगा कि मुझे कितना प्रदर्शन मिल सकता है?

स्टैक के नमूने आपको किस अंश का बहुत मोटा अनुमान देंगे xβ(s+1,(ns)+1)sn1/(1x)n=10s=5x
यहाँ छवि विवरण दर्ज करें
xx

जैसा कि मैंने आपको पहले बताया है, आप पूरी प्रक्रिया दोहरा सकते हैं जब तक कि आप किसी भी अधिक नहीं कर सकते, और मिश्रित गति अनुपात काफी बड़ा हो सकता है।

(s+1)/(n+2)=3/22=13.6%।) निम्नलिखित ग्राफ में निम्न वक्र इसका वितरण है:

यहाँ छवि विवरण दर्ज करें

विचार करें कि क्या हमने 40 से अधिक नमूने लिए हैं (एक समय में मेरे पास जितना अधिक है) और केवल उनमें से दो पर एक समस्या देखी गई। उस समस्या की अनुमानित लागत (मोड) 5% है, जैसा कि लम्बे वक्र पर दिखाया गया है।

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

एक अधिक गंभीर जोखिम है - एक "गलत नकारात्मक"। वह तब है जब कोई समस्या है, लेकिन यह नहीं मिली है। (इसमें योगदान "पुष्टिकरण पूर्वाग्रह" है, जहां साक्ष्य के अभाव को अनुपस्थिति के साक्ष्य के रूप में माना जाता है।)

आपको एक प्रोफाइलर (एक अच्छा) के साथ क्या मिलता है क्या आपको अधिक सटीक माप प्राप्त होती है (इस प्रकार गलत सकारात्मकता की संभावना कम है), वास्तव में समस्या क्या है (इस प्रकार इसे खोजने और प्राप्त करने की कम संभावना कोई भी लाभ)। यह समग्र गति को सीमित करता है जिसे प्राप्त किया जा सकता है।

मैं प्रोफाइलरों के उपयोगकर्ताओं को वास्तव में व्यवहार में आने वाले स्पीडअप कारकों की रिपोर्ट करने के लिए प्रोत्साहित करूंगा।


फिर से बनाए जाने का एक और बिंदु है। झूठी सकारात्मकता के बारे में पेड्रो का सवाल।

उन्होंने कहा कि अत्यधिक अनुकूलित कोड में छोटी समस्याओं के लिए नीचे उतरने में कठिनाई हो सकती है। (मेरे लिए, एक छोटी समस्या वह है जो कुल समय का 5% या उससे कम है।)

चूंकि 5% को छोड़कर पूरी तरह से इष्टतम होने वाले कार्यक्रम का निर्माण पूरी तरह से संभव है, इस बिंदु को केवल अनुभवजन्य रूप से संबोधित किया जा सकता है, जैसा कि इस उत्तर में है । अनुभवजन्य अनुभव से सामान्यीकरण करने के लिए, यह इस प्रकार है:

एक कार्यक्रम, जैसा कि लिखा गया है, आमतौर पर अनुकूलन के लिए कई अवसर होते हैं। (हम उन्हें "समस्याएं" कह सकते हैं, लेकिन वे अक्सर पूरी तरह से अच्छे कोड होते हैं, बस काफी सुधार करने में सक्षम होते हैं।) यह आरेख एक कृत्रिम कार्यक्रम दिखाता है जिसमें कुछ समय (100s, कहते हैं), और इसमें समस्याएं A, B, C शामिल हैं। ... कि, जब पाया और तय किया, तो मूल 100 के 30%, 21% आदि को बचाएं।

यहाँ छवि विवरण दर्ज करें

ध्यान दें कि समस्या एफ मूल समय का 5% है, इसलिए यह "छोटा" है, और 40 या अधिक नमूनों के बिना खोजना मुश्किल है।

हालांकि, पहले 10 नमूने आसानी से समस्या ए पाते हैं। ** जब यह तय हो जाता है, तो 100/70 = 1.43x के स्पीडअप के लिए कार्यक्रम केवल 70s लेता है। यह न केवल कार्यक्रम को तेज बनाता है, यह उस अनुपात से, शेष समस्याओं द्वारा लिया गया प्रतिशत बढ़ाता है। उदाहरण के लिए, समस्या B ने मूल रूप से 21s लिया जो कुल का 21% था, लेकिन A को हटाने के बाद, B 70 में से 21 या 30% लेता है, इसलिए यह पता लगाना आसान है कि पूरी प्रक्रिया कब दोहराई जाती है।

एक बार प्रक्रिया को पांच बार दोहराया जाता है, अब निष्पादन का समय 16.8 है, जिसमें से समस्या एफ 30% है, 5% नहीं, इसलिए 10 नमूने आसानी से मिल जाते हैं।

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

यदि एफ के माध्यम से समस्याएं आती हैं और तय की जाती हैं, तो स्पीडअप 100 / 11.8 = 8.5x है। यदि उनमें से एक छूट गया है, उदाहरण के लिए डी, तो स्पीडअप केवल 100 / (11.8 + 10.3) = 4.5x है। यह झूठी नकारात्मक के लिए भुगतान की गई कीमत है।

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

2/0.3=6.671 - pbinom(1, numberOfSamples, sizeOfProblem)1 - pbinom(1, 20, 0.3) = 0.9923627

xβ(s+1,(ns)+1)nsy1/(1x)xyy1BetaPrime वितरण। मैंने इसे व्यवहार में लाते हुए 2 मिलियन नमूनों के साथ अनुकरण किया:

         distribution of speedup
               ratio y

 s, n    5%-ile  95%-ile  mean
 2, 2    1.58    59.30   32.36
 2, 3    1.33    10.25    4.00
 2, 4    1.23     5.28    2.50
 2, 5    1.18     3.69    2.00
 2,10    1.09     1.89    1.37
 2,20    1.04     1.37    1.17
 2,40    1.02     1.17    1.08

 3, 3    1.90    78.34   42.94
 3, 4    1.52    13.10    5.00
 3, 5    1.37     6.53    3.00
 3,10    1.16     2.29    1.57
 3,20    1.07     1.49    1.24
 3,40    1.04     1.22    1.11

 4, 4    2.22    98.02   52.36
 4, 5    1.72    15.95    6.00
 4,10    1.25     2.86    1.83
 4,20    1.11     1.62    1.31
 4,40    1.05     1.26    1.14

 5, 5    2.54   117.27   64.29
 5,10    1.37     3.69    2.20
 5,20    1.15     1.78    1.40
 5,40    1.07     1.31    1.17

(n+1)/(ns)s=ny

यह स्पीडअप कारकों के वितरण की एक साजिश है, और उनके साधन, 5, 4, 3 और 2 नमूनों में से 2 हिट के लिए। उदाहरण के लिए, यदि 3 नमूने लिए गए हैं, और उनमें से 2 एक समस्या पर हिट हैं, और उस समस्या को हटाया जा सकता है, औसत स्पीडअप कारक 4x होगा। यदि 2 हिट केवल 2 नमूनों में देखे जाते हैं, तो औसत स्पीड अप अपरिभाषित है - वैचारिक रूप से क्योंकि अनंत छोरों वाले कार्यक्रम गैर-शून्य संभावना के साथ मौजूद हैं!

यहाँ छवि विवरण दर्ज करें


1
उह ... क्या आपको यह जानकारी प्राप्त नहीं हुई है कि प्रोफाइलर कॉल ग्राफ या "बॉटम-अप" प्रकार के सारांश वीट्यून द्वारा दिए गए हैं?
पेड्रो

2
@Proro: यदि केवल। स्टैक सैंपल (और संबंधित वैरिएबल) में पूरे कारण को एन्कोड किया गया है कि समय की वृद्धि खर्च की जा रही है। जब तक आप यह नहीं जानते कि यह क्यों खर्च हो रहा है, आप इससे छुटकारा नहीं पा सकते। कुछ समस्याओं को सीमित जानकारी के साथ पाया जा सकता है, लेकिन हर एक को नहीं । यदि आप केवल उनमें से कुछ को प्राप्त करते हैं, लेकिन हर एक को नहीं, तो आप जिन समस्याओं को समाप्त नहीं करते हैं वे आपको आगे के स्पीडअप से अवरुद्ध करते हैं। यहाँ और यहाँ की जाँच करें
माइक डनलवे जुले

यकीनन, आप अपने तरीके की तुलना खराब प्रोफाइलिंग से कर रहे हैं ... आप प्रत्येक रूटीन के लिए प्रोफ़ाइल के माध्यम से भी जा सकते हैं, जो कुल निष्पादन समय में इसके योगदान से स्वतंत्र है, और सुधार के लिए समान प्रभाव के साथ देख सकते हैं। आपके दृष्टिकोण में मुझे जो चिंता है, वह है झूठी सकारात्मकता की बढ़ती संख्या जिसे आप ट्रैक करना समाप्त कर देंगे क्योंकि आपके कोड में "हॉटस्पॉट्स" छोटे और छोटे हो जाएंगे।
पेड्रो

@ पेड्रो: बस नमूने लेते रहें जब तक आपको कुछ दिखाई न दे आप एक से अधिक नमूनों को ठीक कर सकते हैं। बीटा डिस्ट्रिक्ट बताता है कि आप इसे कितना बचा सकते हैं, अगर आप परवाह करते हैं, लेकिन अगर आप इससे कम स्पीडअप होने का डर दिखाते हैं, तो ध्यान रखें कि आप इस संभावना को दूर फेंक रहे हैं कि यह अधिक भी हो सकता है (और यह सही-तिरछा है )। प्रोफाइलर्स को सारांशित करने के साथ बड़ा खतरा, झूठे नकारात्मक हैं । कोई समस्या हो सकती है, लेकिन आप उम्मीद कर रहे हैं कि आपका अंतर्ज्ञान इसे सूँघ लेगा जब प्रोफाइलर बहुत विशिष्ट नहीं हो सकता है, जहां यह नहीं होना चाहिए।
माइक डनलवे जुले

@Pedro: जब मुझे पता है कि केवल कमजोरी है, तो इस समय स्नैपशॉट को देखते हुए, आप यह पता नहीं लगा सकते हैं कि उस समय को क्यों बिताया जा रहा है, जैसे कि यह बस अतुल्यकालिक घटनाओं को संसाधित कर रहा है जहां अनुरोधकर्ता छुपा रहा है, या अतुल्यकालिक प्रोटोकॉल। अधिक "सामान्य" कोड के लिए, मुझे एक "अच्छा" प्रोफाइलर दिखाएं और मैं आपको एक समस्या दिखाऊंगा जिसके साथ यह समस्या है या बस नहीं मिल सकती है (आपको अपने गिरने योग्य स्मार्ट पर वापस आती है)। आम तौर पर इस तरह की समस्या के निर्माण का तरीका यह सुनिश्चित करना है कि जिस उद्देश्य से सेवा दी जा रही है, उसे स्थानीय स्तर पर तय नहीं किया जा सकता है। और इस तरह की समस्याओं सॉफ्टवेयर में लाजिमी है।
माइक डनलैवी

23

न केवल आपको अपने संकलक का अंतरंग ज्ञान होना चाहिए , आपको अपने लक्ष्य वास्तुकला और ऑपरेटिंग सिस्टम का भी अंतरंग ज्ञान होना चाहिए ।

प्रदर्शन को क्या प्रभावित कर सकता है?

यदि आप प्रदर्शन के हर अंतिम औंस को निचोड़ना चाहते हैं, तो हर बार जब आप अपना लक्ष्य आर्किटेक्चर बदलते हैं, तो आपको अपने कोड को फिर से चुनना और पुनः अनुकूलित करना होगा। कुछ जो एक सीपीयू के साथ अनुकूलन था, उसी सीपीयू के अगले संशोधन में उप-इष्टतम बन सकता है।

इसका एक उत्कृष्ट उदाहरण CPU कैश होगा। एक सीपीयू से अपने प्रोग्राम को तेज छोटे कैश के साथ थोड़ा धीमे, थोड़े बड़े कैश के साथ घुमाएं और आपकी प्रोफाइलिंग काफी बदल सकती है।

यहां तक ​​कि अगर लक्ष्य वास्तुकला नहीं बदलता है, तो ऑपरेटिंग सिस्टम में निम्न स्तर के परिवर्तन भी प्रदर्शन को प्रभावित कर सकते हैं। स्पेक्टर और मेल्टडाउन मिटिंग पैच का कुछ वर्कलोड में बहुत अधिक प्रभाव था, इसलिए ये आपके अनुकूलन के पुनर्मूल्यांकन को मजबूर कर सकते हैं।

मैं अपने कोड को कैसे अनुकूलित रख सकता हूं?

अत्यधिक अनुकूलित कोड विकसित करते समय, आपको इसे मॉड्यूलर रखना होगा और अंदर और बाहर एक ही एल्गोरिथ्म के विभिन्न संस्करणों को स्वैप करना आसान होगा, संभवतः उपलब्ध समय में उपयोग किए जाने वाले विशिष्ट संस्करण का चयन करना, उपलब्ध संसाधनों और आकार / जटिलता के आधार पर। डेटा संसाधित किया जाना है।

प्रतिरूपकता का अर्थ है कि आपके सभी अनुकूलित और अडॉप्ट किए गए संस्करणों पर एक ही टेस्ट सूट का उपयोग करने में सक्षम होना, आपको यह सत्यापित करने की अनुमति देता है कि वे सभी समान व्यवहार करते हैं और एक -जैसे तुलना में प्रत्येक को जल्दी से प्रोफाइल करते हैं । मैं अपने उत्तर में थोड़ा और विस्तार में जाता हूं कैसे दूसरों को "मान्यता से परे अनुकूलित" कम्प्यूटेशनल रूप से गहन कोड को पढ़ाने और सिखाने के लिए?

आगे की पढाई

इसके अलावा, मैं अत्यधिक उलरिक ड्रेपर के उत्कृष्ट पेपर पर ध्यान देने की सलाह दूंगा जो प्रत्येक प्रोग्रामर को मेमोरी के बारे में जानना चाहिए , जिसका शीर्षक डेविड गोल्डबर्ग के लिए समान रूप से शानदार है जो हर कंप्यूटर वैज्ञानिक फ्लोटिंग-पॉइंट अंकगणित के बारे में जानना चाहिए।

याद रखें कि हर अनुकूलन में भविष्य के विरोधी अनुकूलन बनने की क्षमता होती है , इसलिए इसे एक न्यूनतम के लिए संभव कोड गंध माना जाना चाहिए। कोडिंग करते समय माइक्रो-ऑप्टिमाइज़ेशन के लिए मेरा उत्तर महत्वपूर्ण है? व्यक्तिगत अनुभव से इसका एक ठोस उदाहरण प्रदान करता है।


8

मुझे लगता है कि आप प्रश्न को बहुत संकीर्ण रूप से उद्धृत करते हैं। मेरे विचार में, एक उपयोगी दृष्टिकोण इस धारणा के तहत रहना है कि केवल डेटा संरचनाओं और एल्गोरिदम में परिवर्तन कोडों पर महत्वपूर्ण प्रदर्शन लाभ प्राप्त कर सकते हैं जो कुछ 100 लाइनों से अधिक हैं, और मुझे विश्वास है कि मुझे अभी तक एक प्रतिसाद प्राप्त करना है यह दावा है।


3
सिद्धांत रूप में सहमत, लेकिन एक एल्गोरिथ्म / डेटा-संरचना और अंतर्निहित हार्डवेयर के विवरण के प्रदर्शन के बीच परस्पर क्रिया को कम नहीं समझना चाहिए। उदा। संतुलित बाइनरी पेड़ डेटा की खोज / भंडारण के लिए महान हैं, लेकिन वैश्विक मेमोरी की विलंबता के आधार पर, एक हैश-टेबल बेहतर हो सकता है।
पेड्रो

1
माना। एल्गोरिदम और डेटा संरचना ओ (10) को ओ (100) सुधार प्रदान कर सकते हैं। हालांकि, कुछ गणना की गई समस्याओं के लिए (जैसा कि आणविक गतिशीलता में गणना, खगोल भौतिकी, वास्तविक समय छवि और वीडियो प्रसंस्करण, वित्त) एक उच्च ट्यून किए गए महत्वपूर्ण लूप का मतलब एक 3x से 10x तेज समग्र अनुप्रयोग रनटाइम हो सकता है।
fcruz

मैंने बुरी तरह से आदेश दिया नेस्टेड छोरों को पर्याप्त आकार के "उत्पादन" कोड में देखा है। इसके अलावा मुझे लगता है कि तुम सही हो।
dckckee

8

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

लिनक्स

gprof बहुत अच्छा है, लेकिन यह केवल आपको बताता है कि प्रत्येक पंक्ति के बजाय प्रत्येक फ़ंक्शन को कितना समय लगता है।

Apple OS X

आप शार्क को आज़माना चाहते हैं । यह Apple डेवलपर साइट में डाउनलोड> डेवलपर टूल्स> CHUD 4.6.2, पुराने संस्करण के तहत उपलब्ध है । CHUD में अन्य प्रोफाइलिंग टूल जैसे BigTop frontend, PMC Index search tool, Saturn function-level profiler और बहुत सारे अन्य कमांड शामिल हैं। शार्क एक कमांडलाइन संस्करण के साथ आएगी।


+1 प्रोफ़ाइल? हां, एक तरह से ... यह अनुमान लगाने से कहीं बेहतर है, लेकिन यहां उन मुद्दों की एक सूची है जो विशेष रूप से लाभकारी और कई अन्य प्रोफाइलर्स पर लागू होते हैं।
माइक डनलैवी

क्या शार्क ओएस एक्स में एक पुरानी कमांड है? अधिक यहाँ । माउंटेन लायन के साथ, क्या मुझे इंस्ट्रूमेंट्स का इस्तेमाल करना चाहिए?
hhh

@hhh: यह macs के लिए एक GUI प्रोफाइलर था, हालांकि ऐसा लगता है कि अब इसे बनाए नहीं रखा जा रहा है। मैंने एक सेब मशीन पर प्रोग्राम नहीं किया है क्योंकि मैंने यह उत्तर लिखा है, इसलिए मैं आपकी बहुत मदद नहीं कर सकता।
दान

1
यह Apple डेवलपर साइट में डाउनलोड> डेवलपर टूल> CHUD 4.6.2 के तहत उपलब्ध है। पुराने संस्करण यहाँ "निर्माता से संपर्क करें", बग के बारे में कोई जानकारी नहीं है: दुर्भाग्य से इस स्थापना सफल नहीं है - और यह चीजों की रूपरेखा के सभी प्रकार के होते हैं। शार्क को शेर के बाद जाहिरा तौर पर Xcode से बाहर ले जाया गया और बाद में MacUpdate में मुफ्त टूल होने के बाद Apple देव साइट पर वापस डाल दिया गया।
hhh

@ ह्ह्ह: आप मुझे इसका जवाब देने के लिए अधिक योग्य लगते हैं। इसे अद्यतन करने के लिए मेरे उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें, या अपना स्वयं का लिखें।
दान

7

जैसा कि आप कितना प्रदर्शन प्राप्त कर सकते हैं, अपने कोड की रूपरेखा से परिणाम लें और मान लें कि आप उस टुकड़े की पहचान करते हैं जो उस समय का "पी" अंश लेता है। यदि आप केवल "एस" के एक कारक द्वारा उस टुकड़े के प्रदर्शन में सुधार करना चाहते थे, तो आपका समग्र स्पीडअप 1 / ((1-p) + p / s) होगा। इसलिए आप अधिकतम 1 / (1-p) के कारक से अपनी गति बढ़ा सकते हैं। उम्मीद है कि आपके पास उच्च पी के क्षेत्र हैं! यह धारावाहिक अनुकूलन के लिए अमदहल के कानून के बराबर है ।


5

अपने कोड का अनुकूलन सावधानी से करना होगा। चलिए मान भी लेते हैं कि आपने पहले ही कोड को डिबग कर लिया है। यदि आप कुछ प्राथमिकताओं का पालन करते हैं, तो आप बहुत समय बचा सकते हैं:

  1. जहाँ संभव हो, अत्यधिक अनुकूलित (या व्यावसायिक रूप से अनुकूलित) पुस्तकालयों का उपयोग करें। कुछ उदाहरणों में FFTW, OpenBlas, Intel MKL, NAG लाइब्रेरी आदि शामिल हो सकते हैं, जब तक कि आप अत्यधिक प्रतिभाशाली नहीं हैं (जैसे GotoBLAS के डेवलपर), आप शायद पेशेवरों को हरा नहीं सकते।

  2. एक प्रोफाइलर का उपयोग करें (निम्न सूची में कुछ पहले से ही इस धागे में नामित किए गए हैं - इंटेल ट्यून, वैलेग्रिंड, ग्रिटोव, जीसीओवी, आदि) यह पता लगाने के लिए कि आपके कोड के किन हिस्सों में सबसे अधिक समय लगता है। कोई बिंदु बर्बाद करने वाला समय कोड के भागों का अनुकूलन करने वाला समय जो शायद ही कभी कहा जाता है।

  3. प्रोफाइलर परिणामों से, अपने कोड के उस भाग को देखें जिसमें सबसे अधिक समय लगा। निर्धारित करें कि आपके एल्गोरिथ्म की प्रकृति क्या है - क्या यह सीपीयू बाध्य है या मेमोरी बाउंड है? प्रत्येक को अनुकूलन तकनीकों के एक अलग सेट की आवश्यकता होती है। यदि आप बहुत अधिक कैश मिस कर रहे हैं, तो मेमोरी टोंटी हो सकती है - सीपीयू घड़ी चक्रों को बर्बाद कर रहा है जो मेमोरी के उपलब्ध होने की प्रतीक्षा कर रहा है। इस बारे में सोचें कि क्या लूप आपके सिस्टम के L1 / L2 / L3 कैश में फिट बैठता है। यदि आपके पास आपके लूप में "if" स्टेटमेंट्स हैं, तो जांच लें कि क्या प्रोफाइलर गलत शाखा के बारे में कुछ कहता है? आपके सिस्टम की शाखा गलत दंड क्या है? वैसे, आप इंटेल ऑप्टिमाइज़ेशन रेफरेंस मैनुअल [1] से शाखा मिसप्रिंट डेटा प्राप्त कर सकते हैं। ध्यान दें कि शाखा मिसप्रिंटेड पेनल्टी प्रोसेसर-विशिष्ट है, जैसा कि आप इंटेल मैनुअल में देखेंगे।

  4. अंत में, प्रोफाइलर द्वारा पहचानी गई समस्याओं का समाधान करें। यहां कई तकनीकों पर पहले ही चर्चा की जा चुकी है। अनुकूलन पर कई अच्छे, विश्वसनीय, व्यापक संसाधन भी उपलब्ध हैं। सिर्फ दो का नाम रखने के लिए, इंटेल ऑप्टिमाइज़ेशन रेफरेंस मैनुअल [1] है, और एग्नर फॉग [2] द्वारा पांच ऑप्टिमाइज़ेशन मैनुअल हैं। ध्यान दें कि कुछ चीजें हैं जो आपको करने की आवश्यकता नहीं हो सकती है, यदि कंपाइलर पहले से ही करता है - उदाहरण के लिए, लूप अनरोलिंग, मेमोरी संरेखित करना आदि। अपने कंपाइलर प्रलेखन को ध्यान से पढ़ें।

संदर्भ:

[१] इंटेल ६४ और आईए -३२ आर्किटेक्चर ऑप्टिमाइज़ेशन संदर्भ मैनुअल: http://www.intel.sg/content/dam/doc/manual/64-ia-32-altectures-optimization-manual.pdf

[२] एग्नर फॉग, "सॉफ्टवेयर ऑप्टिमाइज़ेशन रिसोर्स": http://www.agner.org/optimize/

  • "C ++ में ऑप्टिमाइज़िंग सॉफ्टवेयर: विंडोज, लिनक्स और मैक प्लेटफॉर्म के लिए एक अनुकूलन गाइड"
  • "असेंबली भाषा में सबरूटीन का अनुकूलन: x86 प्लेटफॉर्म के लिए एक अनुकूलन गाइड"
  • "इंटेल, एएमडी और वीआईए सीपीयू के माइक्रोआर्किटेक्चर: असेंबली प्रोग्रामर और कंपाइलर निर्माताओं के लिए एक अनुकूलन गाइड"
  • "निर्देश तालिका: इंटेल, एएमडी और वीईए सीपीयू के लिए निर्देश विलंबता, थ्रूपुट और माइक्रो-ऑपरेशन ब्रेकडाउन की सूची।"
  • "विभिन्न सी ++ कंपाइलर और ऑपरेटिंग सिस्टम के लिए कॉलिंग कन्वेंशन"

3

मैं यहां कई अन्य लोगों के रूप में एक कम्प्यूटेशनल वैज्ञानिक नहीं हूं (इसलिए मैं गलत हो सकता हूं :)) लेकिन इन दिनों सीरियल के प्रदर्शन पर बहुत अधिक समय खर्च करने का कोई मतलब नहीं है क्योंकि हम मानक कामों का उपयोग करते हैं। कोड को और अधिक स्केलेबल बनाने पर किसी भी अतिरिक्त समय / प्रयास को खर्च करना अधिक सार्थक हो सकता है।

किसी भी मामले में यहां दो उदाहरण हैं (यदि आप पहले से ही उन्हें पढ़ चुके हैं) प्रदर्शन में सुधार कैसे किया गया था (असंरचित FE समस्याओं के लिए)।

सीरियल : सार और संबंधित पाठ का दूसरा भाग देखें।

समानांतर : विशेष रूप से प्रारंभिक चरण, 4.2 सेकंड में।


3

यह शायद मेटा-उत्तर का एक उत्तर से अधिक है ...

आपको अपने संकलक के साथ एक अंतरंग परिचित विकसित करना होगा। आप मैन्युअल रूप से पढ़कर और विकल्पों के साथ प्रयोग करके इसे सबसे कुशलता से प्राप्त कर सकते हैं।

कार्यक्रम के बजाय संकलन को समायोजित करके @Pedro डिस्पेंस को लागू करने के लिए बहुत अच्छी सलाह दी जा सकती है।


मैं अंतिम बिंदु से असहमत हूं। यह जानना कि आपका कंपाइलर क्या कर सकता है, एक बात है, लेकिन अपना कोड लिखना ताकि आपका कंपाइलर वास्तव में इसके साथ कुछ कर सके, एक पूरी तरह से अलग समस्या है। कोई कंपाइलर फ़्लैग नहीं हैं जो आपके लिए आपके डेटा को सॉर्ट करेंगे, आवश्यकता पड़ने पर कम सटीकता का उपयोग करेंगे या अपने अंतरतम छोरों को फिर से लिखेंगे जैसे कि उनके पास कुछ या कोई शाखा नहीं है। अपने कंपाइलर को जानना अच्छी बात है, लेकिन यह आपको बेहतर कोड लिखने में मदद करेगा, यह आपके कोड को बेहतर नहीं बना सकता है।
पेड्रो

1

प्रोग्राम (लिनक्स में) को प्रोफाइल करने का एक आसान तरीका मोड perfमें उपयोग करना statहै। सबसे सरल तरीका बस इसे चला रहा है

perf stat ./my_program args ...

और यह आपको उपयोगी प्रदर्शन आंकड़ों का एक गुच्छा देगा:

Performance counter stats for './simd_test1':

     3884.559489 task-clock                #    1.000 CPUs utilized
              18 context-switches          #    0.005 K/sec
               0 cpu-migrations            #    0.000 K/sec
             383 page-faults               #    0.099 K/sec
  10,911,904,779 cycles                    #    2.809 GHz
 <not supported> stalled-cycles-frontend
 <not supported> stalled-cycles-backend
  14,346,983,161 instructions              #    1.31  insns per cycle
   2,143,017,630 branches                  #  551.676 M/sec
          28,892 branch-misses             #    0.00% of all branches

     3.885986246 seconds time elapsed

कभी-कभी यह डी-कैश लोड और मिस को भी सूचीबद्ध करेगा। यदि आप बहुत अधिक कैश मिस करते हैं, तो आपका प्रोग्राम मेमोरी इंटेंसिव है और कैश को अच्छी तरह से ट्रीट नहीं कर रहा है। इन दिनों, सीपीयू मेमोरी बैंडविड्थ की तुलना में तेजी से हो रहे हैं, और आमतौर पर समस्या हमेशा मेमोरी एक्सेस होती है।

आप यह भी आज़मा सकते हैं perf record ./my_program; perf reportजो प्रोफ़ाइल करने का एक आसान तरीका है। अधिक जानने के लिए मैन पेज पढ़ें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.