यहाँ GCC 4.7.2 और Clang 3.2 के साथ खदान के लिए कुछ अप-टू-डेट संकीर्ण निष्कर्ष हैं।
अद्यतन: जीसीसी 4.8.1 वी क्लैंग 3.3 तुलना नीचे संलग्न है।
अद्यतन: जीसीसी 4.8.2 वी क्लैंग 3.4 की तुलना में संलग्न है।
मैं एक ओएसएस उपकरण रखता हूं जो लिनक्स के लिए जीसीसी और क्लैंग दोनों के साथ बनाया गया है, और विंडोज के लिए माइक्रोसॉफ्ट के कंपाइलर के साथ। उपकरण, कॉइन, C / C ++ स्रोत फ़ाइलों का प्रीप्रोसेसर और एनालाइज़र है, जो इस प्रकार है: पुनरावर्ती-वंश परसिंग और फ़ाइल-हैंडलिंग पर इसकी कम्प्यूटेशनल प्रोफाइल की बड़ी मात्रा। विकास शाखा (जिससे ये परिणाम प्राप्त होते हैं) में वर्तमान में लगभग 90 फाइल में 11K LOC शामिल है। यह कोडित है, अब, C ++ में जो कि बहुरूपता और टेम्पलेट्स में समृद्ध है और अभी भी हैक-सी में एक साथ इतने दूर के अतीत द्वारा कई पैच में निकाल दिया जाता है। चाल सीमांत का स्पष्ट रूप से शोषण नहीं किया जाता है। यह सिंगल-थ्रेडेड है। मैंने इसे अनुकूलित करने के लिए कोई गंभीर प्रयास नहीं किया है, जबकि "वास्तुकला" इतने बड़े पैमाने पर टूडो है।
मैंने क्लैंग को 3.2 से पहले केवल एक प्रयोगात्मक संकलक के रूप में नियोजित किया, क्योंकि इसकी बेहतर संकलन गति और डायग्नोस्टिक्स के बावजूद, इसके C ++ 11 मानक समर्थन ने समकालीन जीसीसी संस्करण को कोन द्वारा प्रयोग किए जाने वाले सम्मानों में पिछड़ दिया। 3.2 के साथ, इस अंतर को बंद कर दिया गया है।
वर्तमान कॉनन विकास प्रक्रियाओं के लिए मेरा लिनक्स टेस्ट हार्नेस, एक फाइल पार्सर टेस्ट-केस के मिश्रण में लगभग 70K स्रोत फाइलें, <1K फाइलों की खपत करने वाली फाइलों और परिदृश्य परीक्षणों की खपत के तनाव परीक्षण। परीक्षण के परिणामों की रिपोर्ट करने के साथ-साथ हार्नेस जमा हो जाता है और उपभोग की गई फ़ाइलों के योग और कॉन में खपत होने वाले रन समय को प्रदर्शित करता है (यह लिनक्स time
कमांड के लिए प्रत्येक कोन कमांड लाइन को पारित करता है और रिपोर्ट किए गए नंबरों को पकड़ता है और जोड़ता है)। इस तथ्य से समय की चापलूसी की जाती है कि जो भी परीक्षण में 0 औसत दर्जे का समय लगेगा, वे सभी 0 तक जोड़ देंगे, लेकिन ऐसे परीक्षणों का योगदान नगण्य है। समय आँकड़े make check
इस तरह से प्रदर्शित होते हैं :
coan_test_timer: info: coan processed 70844 input_files.
coan_test_timer: info: run time in coan: 16.4 secs.
coan_test_timer: info: Average processing time per input file: 0.000231 secs.
मैंने GCC 4.7.2 और Clang 3.2 के बीच परीक्षण हार्नेस प्रदर्शन की तुलना की, सभी चीजों को संकलक के अलावा बराबर किया गया। क्लैंग 3.2 के रूप में, मुझे अब कोड ट्रैक्स के बीच किसी प्रीप्रोसेसर भेदभाव की आवश्यकता नहीं है जिसे जीसीसी संकलित करेगा और क्लैंग विकल्प। मैंने प्रत्येक मामले में समान C ++ लाइब्रेरी (GCC) का निर्माण किया और सभी तुलनाओं को एक ही टर्मिनल सत्र में लगातार चलाया।
मेरी रिलीज़ बिल्ड के लिए डिफ़ॉल्ट अनुकूलन स्तर -O2 है। मैं भी सफलतापूर्वक परीक्षण -O3 पर बनाता है। मैंने प्रत्येक कॉन्फ़िगरेशन का 3 बार बैक-टू-बैक परीक्षण किया और निम्न परिणामों के साथ 3 परिणामों को औसत किया। डेटा-सेल में संख्या ~ 70K इनपुट फ़ाइलों (पढ़ें, पार्स और राइटिंग आउटपुट और डायग्नोस्टिक्स) में से प्रत्येक को संसाधित करने के लिए coan निष्पादक द्वारा खपत माइक्रोसेकंड की औसत संख्या है।
| -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 231 | 237 |0.97 |
----------|-----|-----|-----|
Clang-3.2 | 234 | 186 |1.25 |
----------|-----|-----|------
GCC/Clang |0.99 | 1.27|
किसी विशेष एप्लिकेशन में एक संकलक की ताकत या कमजोरियों के लिए गलत तरीके से खेलने वाले लक्षण होने की बहुत संभावना है। कठोर बेंचमार्किंग विभिन्न अनुप्रयोगों को रोजगार देती है। यह अच्छी तरह से ध्यान में रखते हुए, इन आंकड़ों की उल्लेखनीय विशेषताएं हैं:
- -O3 अनुकूलन जीसीसी के लिए मामूली हानिकारक था
- -O3 अनुकूलन क्लैंग के लिए महत्वपूर्ण रूप से फायदेमंद था
- At-2 अनुकूलन, GCC क्लिंकर की तुलना में सिर्फ एक मूंछ से तेज था
- At-3 अनुकूलन, Clang जीसीसी की तुलना में महत्वपूर्ण रूप से तेज था।
उन निष्कर्षों के कुछ ही समय बाद दुर्घटना के कारण दो संकलकों की एक और दिलचस्प तुलना सामने आई। Coan उदारतापूर्वक स्मार्ट पॉइंटर्स को नियोजित करता है और इस तरह के एक फ़ाइल हैंडलिंग में भारी व्यायाम किया जाता है। यह विशेष रूप से स्मार्ट-पॉइंटर प्रकार कंपाइलर-विभेदन के लिए पूर्व रिलीज़ में टाइप किए गए थे, std::unique_ptr<X>
यदि कॉन्फ़िगर कंपाइलर के पास इसके उपयोग के लिए पर्याप्त रूप से परिपक्व समर्थन था, और अन्यथा ए std::shared_ptr<X>
। पूर्वाग्रह std::unique_ptr
मूर्खतापूर्ण था, क्योंकि ये संकेत वास्तव में आसपास स्थानांतरित किए गए थे, लेकिन एक बिंदु पर std::unique_ptr
प्रतिस्थापित करने के लिए फिटर विकल्प की तरह देखा गया
std::auto_ptr
जब सी ++ 11 वेरिएंट मेरे लिए उपन्यास थे।
क्लैंग 3.2 को आगे std::shared_ptr<X>
बढ़ाने के लिए प्रायोगिक बिल्डरों के पाठ्यक्रम में इस और इसी तरह की भिन्नता की निरंतर आवश्यकता है, मैंने अनजाने में निर्मित किया था
जब मैंने निर्माण करने का इरादा किया std::unique_ptr<X>
था, और यह देखने के लिए आश्चर्यचकित था कि परिणामी निष्पादन योग्य, डिफ़ॉल्ट -O2 अनुकूलन के साथ, सबसे तेज था देखा है, कभी-कभी 184 मिसे प्राप्त कर रहा है। इनपुट फ़ाइल के अनुसार। इस स्रोत कोड में एक परिवर्तन के साथ, इसी परिणाम ये थे;
| -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 234 | 234 |1.00 |
----------|-----|-----|-----|
Clang-3.2 | 188 | 187 |1.00 |
----------|-----|-----|------
GCC/Clang |1.24 |1.25 |
यहाँ ध्यान देने योग्य बातें हैं:
- न तो कंपाइलर अब -ओ 3 ऑप्टिमाइज़ेशन से लाभान्वित होते हैं।
- क्लैंग जीसीसी को अनुकूलन के प्रत्येक स्तर पर उतना ही महत्वपूर्ण बनाता है।
- जीसीसी का प्रदर्शन केवल स्मार्ट-पॉइंटर प्रकार परिवर्तन से मामूली प्रभावित होता है।
- क्लैंग का -O2 प्रदर्शन स्मार्ट-पॉइंटर प्रकार परिवर्तन से महत्वपूर्ण रूप से प्रभावित होता है।
स्मार्ट-पॉइंटर प्रकार परिवर्तन से पहले और बाद में, क्लॉन्ग-ओ 3 ऑप्टिमाइज़ेशन में काफी तेजी से कोऑन एक्ज़ीक्यूटेबल बनाने में सक्षम है, और यह ओ-ओ 2 और -ओ 3 में समान रूप से तेज़ निष्पादन योग्य बना सकता है जब पॉइंटर-टाइप सबसे अच्छा हो std::shared_ptr<X>
- काम के लिए।
एक स्पष्ट सवाल है कि मैं इस पर टिप्पणी करने के लिए सक्षम नहीं हूं, इसलिए
क्लैंग को मेरे आवेदन में 25% -O2 गति-अप का पता लगाने में सक्षम होना चाहिए जब एक भारी उपयोग किए जाने वाले स्मार्ट-पॉइंटर-प्रकार को अद्वितीय से साझा किया जाता है, जबकि जीसीसी उदासीन है उसी बदलाव के लिए। और न ही मुझे पता है कि मुझे इस खोज को खुश करना चाहिए या बू करना चाहिए कि क्लैंग -ओ 2 अनुकूलन मेरे स्मार्ट-पॉइंटर विकल्पों के ज्ञान के लिए इतनी बड़ी संवेदनशीलता को परेशान करता है।
अद्यतन: जीसीसी 4.8.1 वी क्लैंग 3.3
अब इसी परिणाम हैं:
| -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.1 | 442 | 443 |1.00 |
----------|-----|-----|-----|
Clang-3.3 | 374 | 370 |1.01 |
----------|-----|-----|------
GCC/Clang |1.18 |1.20 |
यह तथ्य कि सभी चार निष्पादनयोग्य अब 1 फ़ाइल को संसाधित करने के लिए पहले की तुलना में अधिक औसत समय लेते हैं , नवीनतम संकलक के प्रदर्शन पर प्रतिबिंबित नहीं करते हैं। यह इस तथ्य के कारण है कि परीक्षण आवेदन के बाद की विकास शाखा ने इस बीच बहुत सारे पार्सिंग परिष्कार किए हैं और इसके लिए गति में भुगतान करता है। केवल अनुपात महत्वपूर्ण हैं।
नोट के बिंदु अब उपन्यास नहीं हैं:
- GCC, -O3 अनुकूलन के प्रति उदासीन है
- -ओ 3 ऑप्टिमाइज़ेशन से क्लैंग को बहुत मामूली लाभ होता है
- क्लेंग जीसीसी के अनुकूलन के प्रत्येक स्तर पर समान रूप से महत्वपूर्ण मार्जिन से धड़कता है।
जीसीसी 4.7.2 और क्लैंग 3.2 के लिए इन परिणामों की तुलना करते हुए, यह पता चलता है कि जीसीसी ने प्रत्येक अनुकूलन स्तर पर क्लैंग के नेतृत्व के एक चौथाई के बारे में वापस आ गया है। लेकिन जब से परीक्षण आवेदन को इस बीच भारी रूप से विकसित किया गया है, तो कोई इसे जीसीसी के कोड-जेनरेशन में विश्वास नहीं कर सकता है। (इस बार, मैंने एप्लिकेशन स्नैपशॉट नोट किया है जिससे समय प्राप्त हुआ था और इसे फिर से उपयोग कर सकते हैं।)
अद्यतन: जीसीसी 4.8.2 वी क्लैंग 3.4
मैंने GCC 4.8.1 v क्लैंग 3.3 के लिए अपडेट को यह कहते हुए समाप्त कर दिया कि मैं आगे के अपडेट के लिए एक ही कॉइन स्नैपशॉट से चिपका रहूंगा। लेकिन मैंने इसके बजाय उस स्नैपशॉट (रेव। 301) पर परीक्षण करने का फैसला किया और नवीनतम विकास स्नैपशॉट पर मेरे पास है कि उसका सुइट सूट (रेव। 619) से गुजरता है। यह परिणामों को थोड़ा देशांतर देता है, और मेरा एक और मकसद था:
मेरी मूल पोस्टिंग में उल्लेख किया गया है कि मैंने गति के लिए कॉनन के अनुकूलन के लिए कोई प्रयास नहीं किया है। यह अभी भी संशोधन के रूप में मामला था। 301. हालांकि, जब मैंने कॉइन टेस्ट हार्नेस में टाइमिंग तंत्र का निर्माण किया था, हर बार जब मैंने टेस्ट सूट चलाया, तो नवीनतम परिवर्तनों के प्रदर्शन प्रभाव ने मुझे चेहरे पर घूर दिया। मैंने देखा कि यह अक्सर आश्चर्यजनक रूप से बड़ा था और यह कि मैं कार्यक्षमता में होने वाले लाभ की तुलना में इस प्रवृत्ति को अधिक नकारात्मक रूप से नकारात्मक मानता था।
उलट कर। 308 परीक्षण सूट में प्रति इनपुट फ़ाइल का औसत प्रसंस्करण समय यहां पहली पोस्टिंग के बाद से दोगुना से अधिक था। उस समय मैंने प्रदर्शन के बारे में परेशान नहीं करने की अपनी 10 साल की नीति पर यू-टर्न लिया। 619 प्रदर्शनों में संशोधन की गहन स्थिति में हमेशा एक विचार किया गया था और उनमें से एक बड़ी संख्या विशुद्ध रूप से तेजी से लाइनों पर कुंजी लोड-बियरर्स को फिर से लिखने के लिए चली गई (हालांकि ऐसा करने के लिए कोई भी गैर-मानक संकलक सुविधाओं का उपयोग किए बिना)। इस यू-टर्न के लिए प्रत्येक कंपाइलर की प्रतिक्रिया को देखना दिलचस्प होगा,
यहाँ अब नवीनतम दो संकलक 'Rev.301 के निर्माण के लिए परिचित समय मैट्रिक्स है:
coan - rev.301 परिणाम
| -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 428 | 428 |1.00 |
----------|-----|-----|-----|
Clang-3.4 | 390 | 365 |1.07 |
----------|-----|-----|------
GCC/Clang | 1.1 | 1.17|
यहां कहानी केवल GCC-4.8.1 और क्लैंग-3.3 से मामूली रूप से बदली गई है। जीसीसी का प्रदर्शन एक बेहतर प्रदर्शन है। क्लैंग एक ट्रिफ़ल बदतर है। इसके लिए शोर अच्छा हो सकता है। क्लैंग अभी भी आगे आया है -O2
और -O3
मार्जिन है कि ज्यादातर अनुप्रयोगों में कोई फर्क नहीं पड़ता, लेकिन काफी कुछ के लिए मायने रखता है।
और यहाँ रेव के लिए मैट्रिक्स है। 619।
coan - rev.619 परिणाम
| -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 210 | 208 |1.01 |
----------|-----|-----|-----|
Clang-3.4 | 252 | 250 |1.01 |
----------|-----|-----|------
GCC/Clang |0.83 | 0.83|
301 और 619 के आंकड़ों को एक साथ लेते हुए, कई बिंदुओं पर बात होती है।
मैं तेजी से कोड लिखने का लक्ष्य बना रहा था, और दोनों संकलक जोर-शोर से मेरे प्रयासों को पूरा करते हैं। परंतु:
जीसीसी उन प्रयासों को क्लैंग की तुलना में कहीं अधिक उदारता से दोहराता है। पर -O2
अनुकूलन बजना के 619 निर्माण 46% अपने 301 निर्माण की तुलना में तेजी है: पर -O3
बजना के सुधार 31% है। अच्छा है, लेकिन प्रत्येक अनुकूलन स्तर पर जीसीसी का 619 बिल्ड अपने 301 के मुकाबले दोगुना से अधिक है।
जीसीसी से अधिक क्लेंग की पूर्व श्रेष्ठता को उलट देता है। और प्रत्येक अनुकूलन स्तर पर GCC अब Clang को 17% से हरा देती है।
301 बिल्ड में क्लैंग की क्षमता -O3
अनुकूलन से जीसीसी की तुलना में अधिक लाभ उठाने के लिए 619 बिल्ड में चली गई है। न तो कंपाइलर से सार्थक लाभ होता है -O3
।
मैं भाग्य के इस उलटफेर से काफी हैरान था कि मुझे शक था कि मैंने गलती से क्लैंग 3.4 का सुस्त निर्माण किया होगा (क्योंकि मैंने इसे स्रोत से बनाया है)। इसलिए मैंने अपने डिस्ट्रो के स्टॉक क्लैंग 3.3 के साथ 619 टेस्ट को फिर से चलाया। परिणाम व्यावहारिक रूप से 3.4 के लिए समान थे।
यू-टर्न की प्रतिक्रिया के रूप में: यहां के नंबरों पर, क्लैंग ने जीसीसी की तुलना में मेरे सी ++ कोड से बाहर गति पर बहुत बेहतर काम किया है जब मैं इसे कोई मदद नहीं दे रहा था। जब मैंने मदद करने का मन बनाया, तो जीसीसी ने क्लैंग की तुलना में बहुत बेहतर काम किया।
मैं उस सिद्धांत को एक सिद्धांत में नहीं बढ़ाता, लेकिन मैं यह सबक लेता हूं कि "कौन सा संकलक बेहतर बायनेरिज़ का उत्पादन करता है?" यह एक प्रश्न है कि, भले ही आप परीक्षण सूट को निर्दिष्ट करते हैं, जिसका उत्तर सापेक्ष होगा, फिर भी केवल बायनेरिज़ के समय का स्पष्ट-कट मामला नहीं है।
क्या आपका बेहतर द्विआधारी सबसे तेज द्विआधारी है, या यह वह है जो सस्ते से तैयार किए गए कोड के लिए सबसे अच्छा मुआवजा देता है? या महंगे
गढ़े हुए कोड के लिए सबसे अच्छा क्षतिपूर्ति करता है जो स्थिरता को प्राथमिकता देता है और गति पर पुन: उपयोग करता है? यह बाइनरी के निर्माण के लिए आपके उद्देश्यों की प्रकृति और सापेक्ष वजन पर निर्भर करता है, और उन बाधाओं के तहत जिनके तहत आप ऐसा करते हैं।
और किसी भी मामले में, यदि आप "सर्वश्रेष्ठ" बायनेरिज़ के निर्माण के बारे में गहराई से ध्यान रखते हैं, तो आपने बेहतर तरीके से जांचा था कि संकलकों के क्रमिक पुनरावृत्तियों ने आपके कोड के क्रमिक पुनरावृत्तियों पर "सर्वश्रेष्ठ" के अपने विचार को कैसे पहुंचाया।