दिलचस्प पोस्ट
सर्कुलर संदर्भ के साथ जावास्क्रिप्ट ऑब्जेक्ट स्ट्रिंग (JSON में कन्वर्ट) स्क्रीन चौड़ाई और ऊंचाई प्राप्त करें वसंत-संदर्भ। Xml का स्थान कांगड़ा 2 में घटना प्रसार रोकें मैं अपने टेम्पलेट के बिना किसी भी MySQL तालिका में सभी डुप्लिकेट रिकॉर्ड कैसे हटाऊं? जावास्क्रिप्ट में कई पंक्तियों में एक लंबी नियमित अभिव्यक्ति कैसे विभाजित है? PHP का उपयोग कर जन ईमेल भेजा जा रहा है विंडोज पर ऊंचा विशेषाधिकार के साथ अजगर स्क्रिप्ट कैसे चलाना एंड्रॉइड: एक बटन या छवि बटन पर पाठ और छवि का संयोजन क्या सीटीई, उप प्रश्न, अस्थाई तालिका या तालिका चर के बीच एक प्रदर्शन अंतर है? जावास्क्रिप्ट के साथ स्क्रॉलबार स्थिति कैसे प्राप्त करें? एंड्रॉइड पर INSTALL_FAILED_INSUFFICIENT_STORAGE त्रुटि का समाधान Printf के लिए एच और एचएच संशोधक का क्या उद्देश्य है? लिनक्स कर्नेल कैसे परीक्षण किया जाता है? डिवि बनाम टेबल्स या सीएसएस बनाम बेवकूफ होने के नाते

C ++ संकलन समय को गति देने के लिए कौन सी तकनीकों का उपयोग किया जा सकता है?

C ++ संकलन समय को गति देने के लिए कौन सी तकनीकों का उपयोग किया जा सकता है?

स्टैक अतिप्रवाह प्रश्न C ++ प्रोग्रामिंग शैली में कुछ टिप्पणियों में यह प्रश्न आया, और मुझे यह सुनना बहुत दिलचस्पी है कि वहां क्या विचार हैं।

मैंने एक संबंधित प्रश्न देखा है, सी ++ संकलन इतने समय क्यों लेता है? , लेकिन यह कई समाधान प्रदान नहीं करता है


यहां वोट दें प्रोजेक्ट्स के बीच विजुअल स्टूडियो समर्थन साझा करने वाले हेडर हैं

वेब के समाधान से एकत्रित समाधान "C ++ संकलन समय को गति देने के लिए कौन सी तकनीकों का उपयोग किया जा सकता है?"

भाषा तकनीक

पिंपल इल्लीम

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

अग्रेषित घोषणाएं

जहां कहीं भी संभव हो, आगे घोषणाओं का उपयोग करें। यदि कंपाइलर को केवल यह जानना SomeIdentifier है कि कुछ SomeIdentifier एक स्ट्रेट या पॉइंटर या जो भी है, तो पूरी परिभाषा शामिल नहीं है, जिससे कम्पाइलर को इसके लिए ज़्यादा काम करने के लिए बाध्य किया जा सकता है। इससे एक व्यापक प्रभाव हो सकता है, जिससे वे इस तरह से धीमी गति से हो सकते हैं

आई / ओ धारा विशेष रूप से बिल्ड को धीमा करने के लिए जाना जाता है अगर आपको उन्हें हेडर फ़ाइल में चाहिए, तो <iosfwd> स्थान पर <iostream> <iosfwd> करने की कोशिश करें और #include <iostream> <iosfwd> केवल कार्यान्वयन फ़ाइल में। <iosfwd> हैडर केवल घोषणाएं रखता है दुर्भाग्य से अन्य मानक शीर्षलेखों की एक संबंधित घोषणा शीर्षलेख नहीं है।

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

गार्ड शर्तों

एक ही अनुवाद इकाई में हेडर फाइल को एक से अधिक बार शामिल किए जाने के लिए गार्ड स्थितियों का उपयोग करें

 #pragma once #ifndef filename_h #define filename_h // Header declarations / definitions #endif 

दोनों प्रोगामा और आईएनडीएफएफ का उपयोग करके, आप सादे मैक्रो समाधान की सुवाह्यता प्राप्त कर सकते हैं, साथ ही साथ संकलन स्पीड ऑप्टिमाइजेशन जो कि कुछ कंपलर्स प्रोग्राम की उपस्थिति में pragma once निर्देशक कर सकते हैं।

अंतर-निर्भरता कम करें

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

कंपाइलर विकल्प

प्रीकंपेल्ड हेडर्स

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

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

ccache एक अन्य उपयोगिता है जो चीजों को गति देने के लिए कैशिंग तकनीक का लाभ लेती है।

समानता का उपयोग करें

कई संकलक / आईडीई एक साथ संकलन करने के लिए एकाधिक कोर / सीपीयू का समर्थन करते हैं। जीएनयू मेक में (आमतौर पर जीसीसी के साथ प्रयोग किया जाता है), -j [N] विकल्प का उपयोग करें। विज़ुअल स्टूडियो में, वरीयताओं के तहत एक विकल्प समानांतर में कई परियोजनाओं को बनाने के लिए अनुमति देता है आप केवल प्रोजेक्ट-लेवल पैरालेलिज़्म के बजाय फ़ाइल-स्तर के पैरालैलिज़्म के लिए /MP विकल्प का उपयोग कर सकते हैं।

अन्य समानांतर उपयोगिताओं:

  • Incredibuild
  • यूनिटी बिल्ड बनाएँ
  • distcc

निम्न अनुकूलन स्तर का उपयोग करें

कंपाइलर अनुकूलित करने की कोशिश करता है, कड़ी मेहनत के लिए उसे काम करना पड़ता है।

साझा पुस्तकालय

अपने कम बार संशोधित कोड को पुस्तकालयों में ले जाने से समय संकलन कम हो सकता है। साझा पुस्तकालयों ( .so या .dll ) का उपयोग करके, आप लिंकिंग समय भी कम कर सकते हैं।

एक तेज़ कंप्यूटर प्राप्त करें

अधिक रैम, तेज हार्ड ड्राइव (SSDs सहित), और अधिक सीपीयू / कोर सभी संकलन की गति में अंतर करेंगे।

मैं इन खेलों से "खेल से भीतर, इंडी गेम डिजाइन और प्रोग्रामिंग" की सिफारिश करता हूं:

  • भौतिक संरचना और सी ++ – भाग 1: एक पहले देखो
  • भौतिक संरचना और सी ++ – भाग 2: बिल्ड टाइम्स
  • इसके साथ भी अधिक प्रयोग भी शामिल हैं
  • कैसे अतुल्य अविश्वसनीय है?
  • पूर्व संकलित हेडरों की देखभाल और भोजन
  • बिल्कुल सही बिल्ड सिस्टम के लिए क्वेस्ट
  • परफेक्ट बिल्ड सिस्टम के लिए क्वेस्ट (भाग 2)

दी, वे बहुत पुरानी हैं – यथार्थवादी परिणाम प्राप्त करने के लिए आपको नवीनतम संस्करण (या आपके लिए उपलब्ध संस्करण) के साथ सब कुछ पुन: परीक्षण करना होगा किसी भी तरह, विचारों के लिए यह एक अच्छा स्रोत है

मैं STAPL प्रोजेक्ट पर काम करता हूं जो एक भारी-थ्रीप्लेटेड सी ++ लाइब्रेरी है। कुछ समय बाद, हमें संकलन समय को कम करने के लिए सभी तकनीकों को फिर से देखना होगा। यहां, मैंने उन तकनीकों का संक्षेप किया है जो हम उपयोग करते हैं। इनमें से कुछ तकनीकों को पहले से ही ऊपर सूचीबद्ध किया गया है:

सबसे अधिक समय लेने वाले वर्गों को ढूंढना

हालांकि प्रतीक लंबाई और संकलन समय के बीच कोई सिद्ध संबंध नहीं है, हमने देखा है कि छोटे औसत प्रतीक आकार सभी कंपाइलर पर संकलन समय को सुधार सकते हैं। तो आपके कोड में सबसे बड़ा प्रतीकों को खोजने के लिए आपका पहला लक्ष्य।

विधि 1 – आकार के आधार पर क्रमबद्ध प्रतीक

आप उनके आकार के आधार पर प्रतीकों की सूची के लिए nm कमांड का उपयोग कर सकते हैं:

 nm --print-size --size-sort --radix=d YOUR_BINARY 

इस कमांड में --radix=d आपको दशमलव संख्याओं में आकार देखता है (डिफ़ॉल्ट हेक्स है)। अब सबसे बड़ा प्रतीक को देखते हुए, पहचान लें कि आप इसी वर्ग को तोड़ सकते हैं और बेस क्लास में गैर-टेम्पल वाले भागों को फैक्टिव करके या क्लास को कई वर्गों में विभाजित करके इसे फिर से डिजाइन करने का प्रयास कर सकते हैं।

विधि 2 – लंबाई के आधार पर क्रमबद्ध प्रतीक

आप नियमित nm कमांड चला सकते हैं और अपनी पसंदीदा स्क्रिप्ट ( एडब्ल्यूके , पायथन , इत्यादि) को अपनी लंबाई के आधार पर प्रतीकों को सॉर्ट करने के लिए पाइप कर सकते हैं। हमारे अनुभव के आधार पर, यह विधि विधि 1 की तुलना में सबसे बड़ी मुसीबत बनाने वाले उम्मीदवारों को पहचानती है।

विधि 3 – उपयोग करें Temlight

" टेम्पलटाइम टेम्पलेट तत्काल प्रक्रिया में आत्मनिरीक्षण प्राप्त करने के लिए इंटरैक्टिव डिबगिंग सत्रों को बनाने के लिए टेम्पलेट इंस्टेंटिशन के समय और मेमरी उपयोग को प्रोफ़ाइल के लिए एक क्लैग- आधारित उपकरण है"।

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

पैच लागू करने के बाद आप अपने कोड को संकलित करने के लिए इंस्टॉलेशन पर निर्दिष्ट बिल्ड फ़ोल्डर में स्थित templight++ उपयोग कर सकते हैं।

सुनिश्चित करें कि templight++ आपके पाथ में है अब संकलित करने के लिए अपने Makefile में या अपने आदेश पंक्ति विकल्पों में अपने CXXFLAGS में निम्नलिखित स्विच जोड़ें:

 CXXFLAGS+=-Xtemplight -profiler -Xtemplight -memory -Xtemplight -ignore-system 

या

 templight++ -Xtemplight -profiler -Xtemplight -memory -Xtemplight -ignore-system 

संकलन के बाद, आपके पास एक .trace.memory.pbf और .trace.pbf एक ही फ़ोल्डर में उत्पन्न होगा। इन निशानों को कल्पना करने के लिए, आप टेम्प्लिट टूल का उपयोग कर सकते हैं जो इन्हें अन्य स्वरूपों में परिवर्तित कर सकते हैं। Temlight-convert को स्थापित करने के लिए इन निर्देशों का पालन करें हम आम तौर पर कॉलग्रिम आउटपुट का उपयोग करते हैं। यदि आपकी परियोजना छोटी है तो आप GraphViz आउटपुट का उपयोग भी कर सकते हैं:

 $ templight-convert --format callgrind YOUR_BINARY --output YOUR_BINARY.trace $ templight-convert --format graphviz YOUR_BINARY --output YOUR_BINARY.dot 

जनरेट किया गया कॉलग्रिंड फ़ाइल को केकेएसीग्रिंड का उपयोग करके खोला जा सकता है जिसमें आप सबसे अधिक समय / मेमरी खपत के तत्काल का पता लगा सकते हैं।

टेम्पलेट इंस्टॉलेशन की संख्या कम करना

हालांकि टेम्पलेट इंस्टाशन की संख्या को कम करने के लिए कोई सटीक समाधान नहीं है, लेकिन कुछ दिशानिर्देश हैं जो मदद कर सकते हैं:

एक से अधिक टेम्पलेट बहुलक के साथ रिएक्टर वर्ग

उदाहरण के लिए, यदि आपके पास एक वर्ग है,

 template <typename T, typename U> struct foo { }; 

और T और U दोनों के 10 अलग-अलग विकल्प हो सकते हैं, आपने 100 से इस वर्ग के संभावित टेम्पलेट इंस्टीटयेशंस को बढ़ा दिया है। इसका समाधान करने का एक तरीका एक अलग वर्ग के कोड का सामान्य भाग है। दूसरी विधि का उपयोग उत्तराधिकार (क्लास पदानुक्रम के पीछे) का उपयोग करना है, लेकिन इस तकनीक का उपयोग करने से पहले सुनिश्चित करें कि आपके डिज़ाइन लक्ष्यों से समझौता नहीं किया गया है।

गैर अनुवादित कोड को अलग-अलग अनुवाद इकाइयों में रिफैक्टर

इस तकनीक का उपयोग करके, आप एक बार आम अनुभाग संकलित कर सकते हैं और इसे बाद में अपने अन्य टीयू (अनुवाद इकाइयों) के साथ लिंक कर सकते हैं।

बाहरी टेम्पलेट इंस्टेंटिशन का उपयोग करें (चूंकि सी ++ 11)

यदि आप एक क्लास के सभी संभावित इंस्टालेशन को जानते हैं तो आप एक अलग अनुवाद इकाई में सभी मामलों को संकलित करने के लिए इस तकनीक का उपयोग कर सकते हैं।

उदाहरण के लिए, में:

 enum class PossibleChoices = {Option1, Option2, Option3} template <PossibleChoices pc> struct foo { }; 

हम जानते हैं कि इस कक्षा में तीन संभावित इंस्टालेशन हो सकते हैं:

 template class foo<PossibleChoices::Option1>; template class foo<PossibleChoices::Option2>; template class foo<PossibleChoices::Option3>; 

उपरोक्त एक अनुवाद इकाई में डालें और क्लास परिभाषा के नीचे, अपनी हैडर फ़ाइल में एक्सटर्न कीवर्ड का उपयोग करें:

 extern template class foo<PossibleChoices::Option1>; extern template class foo<PossibleChoices::Option2>; extern template class foo<PossibleChoices::Option3>; 

यह तकनीक आपको समय बचा सकती है यदि आप इन्टरनेशनल के सामान्य सेट के साथ अलग-अलग परीक्षण संकलित कर रहे हैं।

नोट: MPICH2 इस बिंदु पर स्पष्ट तात्कालिकता की अनदेखी करता है और हमेशा सभी संकलन इकाइयों में तत्काल कक्षाएं संकलित करता है।

उपयोग एकता बनाता है

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

एक उदाहरण के रूप में, मान लें कि आपके पास तीन फाइलें हैं foo1.cc , foo2.cc , foo3.cc और वे सभी एसटीएल से tuple को शामिल करते हैं आप एक foo-all.cc बना सकते हैं जो ऐसा दिखता है:

 #include "foo1.cc" #include "foo2.cc" #include "foo3.cc" 

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

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

प्रीकम्पल किए गए हेडर

प्रीकंपल्ड हेडर (पीसीएचएस) एक संकलक द्वारा पहचानने योग्य मध्यवर्ती प्रतिनिधित्व करने के लिए अपनी हेडर फाइलों को संकलित करके आप संकलन में बहुत समय बचा सकते हैं। Precompiled हेडर फाइल उत्पन्न करने के लिए, आपको केवल अपने हेडर फ़ाइल को अपने नियमित संकलन आदेश के साथ संकलित करने की आवश्यकता है। उदाहरण के लिए, जीसीसी पर:

 $ g++ YOUR_HEADER.hpp 

इससे एक YOUR_HEADER.hpp.gch file (। .gch जीसीसी में .gch फाइलों के लिए एक्सटेंशन है) उसी फ़ोल्डर में उत्पन्न होगी। इसका अर्थ यह है कि यदि आप कुछ अन्य फाइल में YOUR_HEADER.hppYOUR_HEADER.hpp को शामिल करते हैं, तो कंपाइलर आपके YOUR_HEADER.hpp.gch बजाय YOUR_HEADER.hpp को उसी फ़ोल्डर में उपयोग करेगा।

इस तकनीक के साथ दो मुद्दे हैं:

  1. आपको यह सुनिश्चित करना होगा कि हेडर फ़ाइलों को प्रीकंपल किया गया है स्थिर है और वे बदलने नहीं जा रहे हैं ( आप हमेशा अपने मेसेफाइल बदल सकते हैं )
  2. आप केवल एक पीसीएच प्रति संकलन इकाई (अधिकांश compilers पर) शामिल कर सकते हैं इसका मतलब यह है कि अगर आपके पास एक से अधिक हेडर फाइल है जो कि पूर्वकंपली हुई है, तो आपको उन्हें एक फाइल में शामिल करना होगा (जैसे, all-my-headers.hppall-my-headers.hpp ) लेकिन इसका मतलब है कि आपको सभी जगहों पर नई फ़ाइल शामिल करनी होगी। सौभाग्य से, जीसीसी के पास इस समस्या का समाधान है। उपयोग करें -include इसमें -include करें और इसे नया हेडर फ़ाइल दें। आप कॉमा को इस तकनीक का उपयोग करके अलग-अलग फाइल कर सकते हैं।

उदाहरण के लिए:

 g++ foo.cc -include all-my-headers.hpp 

अनाम या अनाम नाम स्थान का उपयोग करें

अनाम नाम स्थान (उर्फ अनाम नामस्थान) उत्पन्न बाइनरी आकार को काफी कम कर सकते हैं अनाम नाम स्थान आंतरिक संबंध का उपयोग करते हैं, जिसका अर्थ है कि उन नामस्थानों में उत्पन्न प्रतीकों को अन्य टीयू (अनुवाद या संकलन इकाइयों) के लिए दिखाई नहीं देगा। कंपाइलर्स आमतौर पर अनाम नाम स्थान के लिए अद्वितीय नाम उत्पन्न करते हैं। इसका मतलब यह है कि यदि आपके पास फ़ाइल foo.hpp है:

 namespace { template <typename T> struct foo { }; } // Anonymous namespace using A = foo<int>; 

और आप इस फ़ाइल को दो टीयू (दो। सीसी फ़ाइलों में शामिल कर सकते हैं और उन्हें अलग से संकलित कर सकते हैं)। दो फू टेम्पलेट उदाहरण समान नहीं होंगे यह एक परिभाषा नियम (ओडीआर) का उल्लंघन करता है। उसी कारण से, नामों के नामों का उपयोग करना हेडर फाइलों में निराश है। अपनी बाइनरी फ़ाइलों में प्रदर्शित होने वाले प्रतीकों से बचने के लिए अपने। सी फाइलों में उनका उपयोग करने के लिए स्वतंत्र महसूस करें। कुछ मामलों में, .cc फ़ाइल के सभी आंतरिक विवरणों को बदलते हुए, उत्पन्न बाइनरी आकार में 10% की कमी दिखायी

दृश्यता विकल्प बदलना

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

दृश्यता की मदद से आप उन प्रतीकों को छुपा सकते हैं, जिन्हें आप उन्हें साझा किए गए ऑब्जेक्ट से निजी मानते हैं। जीसीसी पर आप अपने कंपाइलर के -visibility ऑप्शन के डिफॉल्ट या छुपा के द्वारा प्रतीकों की दृश्यता को नियंत्रित कर सकते हैं। यह कुछ अज्ञात नाम स्थान के समान है लेकिन अधिक विस्तृत और घुसपैठ तरीके से है।

यदि आप प्रत्येक मामले में दृश्यता निर्दिष्ट करना चाहते हैं, तो आपको अपने कार्य, चर और कक्षाओं में निम्नलिखित विशेषताओं को जोड़ना होगा:

 __attribute__((visibility("default"))) void foo1() { } __attribute__((visibility("hidden"))) void foo2() { } __attribute__((visibility("hidden"))) class foo3 { }; void foo4() { } 

जीसीसी में डिफ़ॉल्ट दृश्यता डिफ़ॉल्ट (सार्वजनिक) है, जिसका अर्थ है कि यदि आप उपरोक्त साझा लाइब्रेरी ( -shared ) विधि के रूप में संकलित करते हैं, तो foo2 और class foo3 अन्य foo1 में दिखाई नहीं देगा ( foo1 और foo4 दिखाई देगा)। यदि आप संकलन के -visibility=hidden तो केवल foo1 दृश्यमान होगा यहां तक ​​कि foo4 छिपा हुआ होगा

आप जीसीसी विकी पर दृश्यता के बारे में अधिक पढ़ सकते हैं

इस विषय पर एक पूरी पुस्तक है, जिसका शीर्षक है बड़े पैमाने पर सी ++ सॉफ्टवेयर डिज़ाइन (जॉन लकोस द्वारा लिखित)।

पुस्तक पूर्व-तिथि टेम्पलेट्स, इसलिए उस पुस्तक की सामग्री के लिए "टेम्पलेट का उपयोग करना, भी, संकलक धीमा बना सकता है" जोड़ने के लिए

एक तकनीक जो मेरे लिए अतीत में बहुत अच्छी तरह से काम करती थी: कई सी ++ स्रोत फ़ाइलों को स्वतंत्र रूप से संकलित न करें, बल्कि एक सी ++ फाइल उत्पन्न करती है जिसमें सभी अन्य फाइलें शामिल होती हैं, जैसे:

 // myproject_all.cpp // Automatically generated file - don't edit this by hand! #include "main.cpp" #include "mainwindow.cpp" #include "filterdialog.cpp" #include "database.cpp" 

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

यह तकनीक विभिन्न मामलों में टूट जाती है; उदाहरण के लिए, कंपाइलर को दो या अधिक स्रोत फाइलें उसी नाम के साथ एक वैश्विक फ़ंक्शन घोषित करने के मामले में बाहर निकल जाएंगी। मुझे इस तकनीक को अन्य किसी भी उत्तर में वर्णित नहीं मिला, हालांकि, यही कारण है कि मैं यहां इसका उल्लेख कर रहा हूं।

इसके लिए क्या है, केडीई प्रोजेक्ट ने 1 999 से अनुकूलित बाइनरी बनाने के लिए (संभवतः एक रिलीज के लिए) इस सटीक तकनीक का इस्तेमाल किया। बिल्ड कॉन्फ़िगर स्क्रिप्ट पर स्विच को --enable-final नाम दिया गया था पुरातात्विक रुचि से मैं इस पोस्ट की घोषणा कर रहा हूं जो इस सुविधा की घोषणा करता है: http://lists.kde.org/?l=kde-devel&m=92722836009368&w=2

मैं सिर्फ अपने दूसरे उत्तर से लिंक करूँगा: आप समय को संकलित करने और विजुअल सी ++ परियोजनाओं (मूल सी ++) के लिए समय जोड़ने से कैसे कम करते हैं? । एक और बिंदु जो मैं जोड़ना चाहता हूं, लेकिन जिसके कारण अक्सर समस्याएं precompiled हेडर का उपयोग करना है लेकिन कृपया, उन भागों के लिए केवल उन का उपयोग करें जो शायद ही कभी बदलते हैं (जैसे GUI Toolkit हेडर)। अन्यथा, वे अंत में आपको बचाने के लिए आपको अधिक समय व्यतीत करेंगे।

एक अन्य विकल्प यह है, जब आप जीएनयू मेक के साथ काम करते हैं, -j<N> विकल्प को चालू करने के लिए:

  -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg. 

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

लेकिन लिंकर को ही थ्रेडेड किया जा सकता है, और यह वही है जो GNU gold ELF लिंकर करता है। यह अनुकूलित थ्रेडेड सी ++ कोड है जिसे एएलएफ ऑब्जेक्ट लिंक करने के लिए कहा जाता है कि पुराने ld (और वास्तव में binutils में शामिल) की तुलना में एक परिमाण बहुत तेज है।

यहाँ कुछ हैं:

  • एकाधिक-संकलन कार्य प्रारंभ करके सभी प्रोसेसर कोर का उपयोग करें ( make -j2 एक अच्छा उदाहरण है)।
  • ऑप्टिमाइज़ेशन बंद करें या कम करें (उदाहरण के लिए, जीसीसी -O1 या -O1 से बहुत अधिक है)।
  • Precompiled हेडर का उपयोग करें

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

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

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

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

जब मैं कॉलेज से आया था, पहली वास्तविक उत्पादन योग्य सी ++ कोड मैंने देखा था कि ये रहस्यमय #ifndef … # उन दोनों के बीच में दिए गए निर्देशों जहां हेडर परिभाषित किए गए थे। मैंने उन लड़कों से पूछा जो एक बहुत ही भोले-भरे फैशन में इन व्यापक चीजों के बारे में कोड लिख रहा था और बड़े पैमाने पर प्रोग्रामिंग की दुनिया में पेश किया गया था।

बिंदु पर वापस आना, डुप्लिकेट हैडर परिभाषाओं को रोकने के निर्देशों का उपयोग करना पहली बार मैंने सीखा था जब यह संकलन समय को कम करने आया था।

अधिक रैम

किसी ने रैम के बारे में दूसरे जवाब में बात की। मैंने इसे 80286 और टर्बो सी ++ (आयु से पता चलता है) के साथ किया और परिणाम असाधारण थे। जैसे ही मशीन को दुर्घटनाग्रस्त हो जाने पर डेटा का नुकसान हुआ था।

उपयोग

 #pragma once 

शीर्ष लेख फ़ाइलों के शीर्ष पर, इसलिए यदि वे अनुवाद इकाई में एक से अधिक बार शामिल किए गए हैं, तो शीर्ष लेख का टेक्स्ट केवल एक बार शामिल किया जाएगा और पार्स किया जाएगा

आप यूनिटी बिल्ड का उपयोग कर सकते हैं

  • अपने कंप्यूटर को अपग्रेड करें

    1. क्वाड कोर (या दो-क्वाड सिस्टम) प्राप्त करें
    2. बहुत सारी रैम प्राप्त करें
    3. फ़ाइल I / O देरी को तेजी से कम करने के लिए रैम ड्राइव का उपयोग करें (ऐसी कंपनियां हैं जो आईडीई और सटा रैम ड्राइव बनाती हैं जो हार्ड ड्राइव की तरह कार्य करती हैं)।
  • तब आपके पास अन्य सभी विशिष्ट सुझाव हैं

    1. यदि उपलब्ध हो तो प्रीकंपल्ड हेडर का उपयोग करें
    2. अपनी परियोजना के कुछ हिस्सों के बीच युग्मन की मात्रा कम करें। एक हेडर फाइल को बदलने से आम तौर पर आपकी पूरी परियोजना को पुनः कंपाइलिंग की आवश्यकता नहीं होनी चाहिए।

बस पूर्णता के लिए: एक बिल्ड धीमी हो सकता है क्योंकि बिल्ड सिस्टम बेवकूफ है और साथ ही क्योंकि संकलक इसके काम करने के लिए लंबा समय ले रहा है

यूनिक्स परिवेश में इस विषय की चर्चा के लिए रिकर्सिव को हानिकारक माना जाता है (पीडीएफ) पढ़ें।

आगे की घोषणाओं का उपयोग करें जहां आप कर सकते हैं यदि कोई क्लास घोषणा केवल एक सूचक या किसी प्रकार के संदर्भ का उपयोग करता है, तो आप केवल इसे घोषित कर सकते हैं और कार्यान्वयन फ़ाइल में प्रकार के लिए हेडर शामिल कर सकते हैं।

उदाहरण के लिए:

 // Th class Class2; // Forward declaration class T { public: void doSomething(Class2 &c2); private: Class2 *m_Class2Ptr; }; // T.cpp #include "Class2.h" void Class2::doSomething(Class2 &c2) { // Whatever you want here } 

कम करने का मतलब है कि अगर आप इसे पर्याप्त रूप से करते हैं तो पूर्वप्रक्रमक के लिए बहुत कम काम होता है

आप अपना समय कहां खर्च कर रहे हैं? क्या आप CPU बाध्य हैं? मेमोरी बाध्य? डिस्क बाउंड? क्या आप अधिक कोर का उपयोग कर सकते हैं? अधिक रैम? क्या आपको RAID की आवश्यकता है? क्या आप बस अपने मौजूदा सिस्टम की दक्षता में सुधार करना चाहते हैं?

जीसीसी / जी ++ के तहत, क्या आपने सीसीएश में देखा है? यदि आप make_clean _; _ बहुत कुछ कर रहे हैं तो यह सहायक हो सकता है

डायनेमिक लिंकिंग (.so) स्थिर लिंकिंग (। ए) की तुलना में बहुत अधिक तीव्र हो सकती है। खासकर जब आपके पास धीमे नेटवर्क ड्राइव है चूंकि आपके पास .a फ़ाइल में सभी कोड हैं, जिन्हें संसाधित करने और लिखे जाने की जरूरत है। इसके अतिरिक्त, एक बहुत बड़ा निष्पादन योग्य फाइल डिस्क पर लिखी जानी चाहिए।

मुझे रैम ड्राइव का उपयोग करने के बारे में एक विचार था यह पता चला है कि मेरी परियोजनाओं के लिए यह सभी के बाद इतना बड़ा अंतर नहीं बना रहा है। लेकिन फिर भी वे काफी छोटी हैं कोशिश करो! मुझे सुनने में दिलचस्पी होगी कि यह कितनी मदद करता है

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

यदि आपके पास एक मल्टीकोर प्रोसेसर है, तो दोनों Visual Studio (2005 और बाद के संस्करण) के साथ-साथ जीसीसी समर्थन मल्टी-प्रोसेसर संकलित करता है। यह सुनिश्चित करने के लिए कि आपके पास हार्डवेयर है, सक्षम करने के लिए कुछ है

संकलन समय के बारे में नहीं, बल्कि निर्माण समय के बारे में:

  • यदि आप अपने बिल्डफ़ाइल पर काम कर रहे हैं तो उसी फाइल को पुन: निर्माण करने के लिए ccache का उपयोग करें

  • बनाने के बजाय निंजा-बिल्ड का उपयोग करें मैं वर्तमान में ~ 100 स्रोत फाइलों के साथ एक परियोजना संकलित कर रहा हूं और सब कुछ ccache द्वारा कैश की गई है I 5 मिनट की ज़रूरतें, निंजा 1 से कम

आप अपनी निंजा फ़ाइलों को सीएमके से जीएनआईएनजा से उत्पन्न कर सकते हैं।

यद्यपि "तकनीक" नहीं, मुझे यह पता नहीं लगा कि कई स्रोत फ़ाइलों के साथ Win32 प्रोजेक्ट्स मेरे "हैलो वर्ल्ड" रिक्त प्रोजेक्ट की तुलना में तेजी से संकलित हैं। इस प्रकार, मुझे आशा है कि यह किसी की मदद करता है जैसे मैंने किया।

दृश्य स्टूडियो में, संकलन समय बढ़ाने के लिए एक विकल्प वृद्धिशील लिंकिंग ( / अंतर्निहित ) है। यह लिंक-टाइम कोड जनरेशन ( / एलटीसीजी ) के साथ असंगत है, इसलिए रिलीज बिल्ड करते समय वृद्धिशील लिंक को अक्षम करने के लिए याद रखें।

तेज़ हार्ड डिस्क

संकलक डिस्क पर कई (और संभवतः बड़ी) फ़ाइलें लिखते हैं विशिष्ट हार्ड डिस्क और संकलन के बजाय एसएसडी के साथ कार्य समय बहुत कम है।

लिनक्स पर (और शायद कुछ अन्य * नक्सिक्स), आप वास्तव में आउटपुट पर STARING और किसी अन्य टीटीआई को बदलकर संकलन को गति दे सकते हैं।

यहाँ प्रयोग है: printf मेरे प्रोग्राम को धीमा कर देती है