कितने जीसीसी अनुकूलन स्तर हैं?


101

कितने जीसीसी अनुकूलन स्तर हैं?

मैंने gcc -O1, gcc -O2, gcc -O3 और gcc -O4 आज़माया

अगर मैं वास्तव में बड़ी संख्या का उपयोग करता हूं, तो यह काम नहीं करेगा।

हालाँकि, मैंने कोशिश की है

gcc -O100

और इसे संकलित किया।

कितने अनुकूलन स्तर हैं?


13
@ मिनिटेक आप किस एफएम को देख रहे हैं? यहां तक कि साथ man gccCygwin (12000 अजीब लाइनों) पर आप के लिए खोज कर सकते हैं -Oऔर सब कुछ राज्य नीचे जवाब मिल, और फिर कुछ।
जेन्स

1
@minmaxavg स्रोत को पढ़ने के बाद, मैं आपसे असहमत हूं: इससे बड़ी कोई चीज 3वैसी ही है 3(जब तक वह intओवरफ्लो नहीं होती )। मेरा जवाब देखिए ।
सिरो सेंटिल्ली 郝海东 冠状 iro 事件 法轮功 '

1
वास्तव में, जीसीसी के पास धुनों के अनुकूलन के लिए कई अन्य झंडे हैं। -fomit-stack-pointer उत्पन्न कोड को बदल देगा।
बेसिल स्टायरनेविच 11

जवाबों:


141

पांडित्यपूर्ण होने के लिए, 8 अलग-अलग वैध -O विकल्प हैं जो आप gcc को दे सकते हैं, हालाँकि कुछ ऐसे भी हैं जिनका अर्थ समान है।

इस उत्तर के मूल संस्करण में कहा गया था कि 7 विकल्प थे। जीसीसी ने तब से जोड़ा है-Og से कुल 8 को लाने के लिए है

से आदमी पेज:

  • -O (के समान -O1 )
  • -O0 (कोई ऑप्टिमाइज़ेशन न करें, डिफ़ॉल्ट यदि कोई ऑप्टिमाइज़ेशन स्तर निर्दिष्ट नहीं है)
  • -O1 (न्यूनतम रूप से अनुकूलित करें)
  • -O2 (अधिक अनुकूलित करें)
  • -O3 (और भी अधिक अनुकूलित करें)
  • -Ofast (मानक अनुपालन को तोड़ने के बिंदु पर बहुत आक्रामक तरीके से अनुकूलन करें)
  • -Og (डिबगिंग अनुभव को ऑप्टिमाइज़ करें। -ऑग अनुकूलन को सक्षम करता है जो डिबगिंग में हस्तक्षेप नहीं करता है। यह मानक एडिट-कंपाइल-डिबग चक्र के लिए पसंद का अनुकूलन स्तर होना चाहिए, तेजी से संकलन और एक अच्छा डीबगिंग अनुभव बनाए रखते हुए अनुकूलन का उचित स्तर प्रदान करता है। )
  • -Os(। के लिए आकार अनुकूलन -Osसब के लिए सक्षम बनाता -O2अनुकूलन नहीं है जो आम तौर पर कोड आकार में वृद्धि नहीं करते यह भी आगे कोड आकार को कम करने के लिए बनाया गया अनुकूलन प्रदर्शन करती है।। -Osनिम्नलिखित अनुकूलन झंडे को निष्क्रिय: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version)

प्लेटफॉर्म विशिष्ट अनुकूलन भी हो सकते हैं, जैसा कि @pauldoo नोट, OS X में है -Oz


23
यदि आप मैक ओएस एक्स पर विकसित कर रहे हैं, तो एक अतिरिक्त -Ozसेटिंग है जो "आकार से अधिक आक्रामक रूप से अनुकूलित है -Os": developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/…
pauldoo

6
ध्यान दें: O3 जरूरी नहीं कि O2 से बेहतर हो, भले ही नाम कितना भी सुझाए। दोनों की कोशिश करो।
जोहान डी।

1
@pauldoo 404 पेज, आर्काइव.ऑर्ग से बदलें
noɥʇʎԀʎz

वहाँ भी है -Og, जो सभी अनुकूलन विकल्प हैं जो डिबगिंग के साथ हस्तक्षेप नहीं करते हैं
einpoklum

47

आइए GCC 5.1 के स्रोत कोड की व्याख्या करें कि -O100यह देखने के लिए क्या होता है क्योंकि यह मैन पेज पर स्पष्ट नहीं है।

हम यह निष्कर्ष निकालेंगे:

  • ऊपर कुछ भी -O3करने के लिए INT_MAXके रूप में ही है -O3, लेकिन यह आसानी से, भविष्य में बदल सकता है तो यह पर भरोसा नहीं करते।
  • यदि आप पूर्णांकों से बड़ा दर्ज करते हैं तो GCC 5.1 अपरिभाषित व्यवहार करता है INT_MAX
  • तर्क में केवल अंक हो सकते हैं, या यह इनायत से विफल होता है। विशेष रूप से, यह नकारात्मक पूर्णांकों को शामिल नहीं करता है-O-1

उपप्रोग्राम पर ध्यान दें

सबसे पहले तो याद रखें कि जीसीसी के लिए सिर्फ एक सामने के अंत है cpp, as, cc1, collect2। एक त्वरित ./XXX --helpकहता है कि केवल collect2और cc1ले लो -O, तो चलो उन पर ध्यान केंद्रित करें।

तथा:

gcc -v -O100 main.c |& grep 100

देता है:

COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64'
/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.

तो -Oदोनों के लिए भेजा गया था cc1और collect2

ओ में आम

common.opt एक GCC विशिष्ट CLI विकल्प वर्णन प्रारूप है जिसे इंटर्नल डॉक्यूमेंटेशन में वर्णित किया गया है और C को opth-gen.awk और optc-gen.awk द्वारा अनुवादित किया गया है ।

इसमें निम्नलिखित दिलचस्प लाइनें शामिल हैं:

O
Common JoinedOrMissing Optimization
-O<number>  Set optimization level to <number>

Os
Common Optimization
Optimize for space rather than speed

Ofast
Common Optimization
Optimize for speed disregarding exact standards compliance

Og
Common Optimization
Optimize for debugging experience rather than speed or size

जो सभी Oविकल्पों को निर्दिष्ट करते हैं। ध्यान दें कि -O<n>दूसरे से एक अलग परिवार में कैसे है Os, OfastऔरOg

जब हम निर्माण करते हैं, तो options.hइसमें एक फ़ाइल उत्पन्न होती है:

OPT_O = 139,                               /* -O */
OPT_Ofast = 140,                           /* -Ofast */
OPT_Og = 141,                              /* -Og */
OPT_Os = 142,                              /* -Os */

एक बोनस के रूप में, जबकि हम \bO\nअंदर की ओर इशारा कर रहे हैं common.optहम लाइनों को नोटिस करते हैं:

-optimize
Common Alias(O)

जो हमें सिखाता है कि --optimize(डबल डैश क्योंकि यह फ़ाइल -optimizeपर एक डैश के साथ शुरू होता है .opt) एक अनजाने उपनाम है -Oजिसके लिए इसका उपयोग किया जा सकता है--optimize=3 !

जहां OPT_O का उपयोग किया जाता है

अब हम grep:

git grep -E '\bOPT_O\b'

जो हमें दो फाइलों की ओर इशारा करता है:

चलो पहले नीचे ट्रैक करते हैं opts.c

opts.c: default_options_optimization

सभी opts.cउपयोग अंदर होते हैं:default_options_optimization

हम यह देखने के लिए पीछे हटते हैं कि इस फ़ंक्शन को कौन कॉल करता है, और हम देखते हैं कि एकमात्र कोड पथ है:

  • main.c:main
  • toplev.c:toplev::main
  • opts-global.c:decode_opts
  • opts.c:default_options_optimization

और main.cका प्रवेश बिंदु हैcc1 । अच्छा!

इस समारोह का पहला भाग:

  • integral_argumentजो atoiस्ट्रिंग पर कॉल करता हैOPT_Oइनपुट तर्क को पार्स लिए है
  • opts->x_optimizeजहां optsएक है के अंदर मूल्य संग्रहीत करता है struct gcc_opts

संरचना gcc_opts

व्यर्थ में टटोलने के बाद, हम देखते हैं कि यह structभी उत्पन्न होता है options.h:

struct gcc_options {
    int x_optimize;
    [...]
}

x_optimizeलाइनों से कहाँ आता है:

Variable
int optimize

वर्तमान में common.opt, और वह options.c:

struct gcc_options global_options;

इसलिए हम अनुमान लगाते हैं कि यह वही है जो संपूर्ण कॉन्फ़िगरेशन वैश्विक स्थिति में है, और int x_optimize अनुकूलन मान है।

255 एक आंतरिक अधिकतम है

में opts.c:integral_argument, atoiइनपुट तर्क पर लागू किया जाता है, इसलिए INT_MAXएक ऊपरी बाध्य है। और अगर आप कुछ भी बड़ा करते हैं, तो ऐसा लगता है कि जीसीसी सी अपरिभाषित व्यवहार करता है। आउच?

integral_argumentatoiयदि कोई वर्ण कोई अंक नहीं है, तो भी तर्क को बारीकी से लपेटता है और अस्वीकार करता है। इसलिए नकारात्मक मूल्य अनुग्रहपूर्वक विफल होते हैं।

वापस opts.c:default_options_optimization, हम लाइन देखते हैं:

if ((unsigned int) opts->x_optimize > 255)
  opts->x_optimize = 255;

ताकि ऑप्टिमाइज़ेशन लेवल को छोटा कर दिया जाए 255। पढ़ते समय opth-gen.awkमैं भर आया था:

# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.

और उत्पन्न पर options.h:

struct GTY(()) cl_optimization
{
  unsigned char x_optimize;

जो बताता है कि क्यों छंटनी: विकल्पों को भी अग्रेषित किया जाना चाहिए cl_optimization, जो एक का उपयोग करता हैchar अंतरिक्ष को बचाने के लिए है। तो 255 वास्तव में एक आंतरिक अधिकतम है।

opts.c: maybe_default_options

पर वापस opts.c:default_options_optimization, हम maybe_default_optionsजो दिलचस्प लगता है भर में आते हैं। हम इसे दर्ज करते हैं, और फिर maybe_default_optionजहां हम एक बड़े स्विच तक पहुंचते हैं:

switch (default_opt->levels)
  {

  [...]

  case OPT_LEVELS_1_PLUS:
    enabled = (level >= 1);
    break;

  [...]

  case OPT_LEVELS_3_PLUS:
    enabled = (level >= 3);
    break;

कोई >= 4जांच नहीं है , जो इंगित करता है कि 3सबसे बड़ा संभव है।

फिर हम की परिभाषा के लिए खोज OPT_LEVELS_3_PLUSमें common-target.h:

enum opt_levels
{
  OPT_LEVELS_NONE, /* No levels (mark end of array).  */
  OPT_LEVELS_ALL, /* All levels (used by targets to disable options
                     enabled in target-independent code).  */
  OPT_LEVELS_0_ONLY, /* -O0 only.  */
  OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og.  */
  OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og.  */
  OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og.  */
  OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os.  */
  OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og.  */
  OPT_LEVELS_3_PLUS, /* -O3 and above.  */
  OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os.  */
  OPT_LEVELS_SIZE, /* -Os only.  */
  OPT_LEVELS_FAST /* -Ofast only.  */
};

हा! यह एक मजबूत संकेतक है कि केवल 3 स्तर हैं।

opts.c: default_options_table

opt_levelsइतना दिलचस्प है, कि हम मचलते हैं OPT_LEVELS_3_PLUS, और सामने आते हैं opts.c:default_options_table:

static const struct default_options default_options_table[] = {
    /* -O1 optimizations.  */
    { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
    [...]

    /* -O3 optimizations.  */
    { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
    [...]
}

इसलिए यह वह जगह है जहां -Onडॉक्स में उल्लिखित विशिष्ट अनुकूलन मानचित्रण एन्कोडेड है। अच्छा!

आश्वासन दें कि x_optimize के लिए और अधिक उपयोग नहीं हैं

का मुख्य उपयोग मैन पेज पर प्रलेखित x_optimizeअन्य विशिष्ट अनुकूलन विकल्पों को सेट करना था -fdefer_pop। क्या कोई और है?

हम grep, और कुछ और पाते हैं। संख्या छोटी है, और मैनुअल निरीक्षण पर हम देखते हैं कि हर उपयोग केवल एक ही पर होता है x_optimize >= 3, इसलिए हमारा निष्कर्ष है।

LTO-wrapper.c

अब हम दूसरी घटना के लिए जाते हैं OPT_O, जो अंदर थी lto-wrapper.c

एलटीओ का अर्थ है लिंक टाइम ऑप्टिमाइज़ेशन, जैसा कि नाम से पता चलता है कि एक -Oविकल्प की आवश्यकता है, और इसे collec2(जो मूल रूप से एक लिंक है) से जोड़ा जाएगा ।

वास्तव में, पहली पंक्ति lto-wrapper.cकहती है:

/* Wrapper to call lto.  Used by collect2 and the linker plugin.

इस फ़ाइल में, OPT_Oआवृत्तियाँ केवल Oइसे आगे पास करने के लिए मान को सामान्य करती हैं, इसलिए हमें ठीक होना चाहिए।


38

सात अलग-अलग स्तर:

  • -O0 (डिफ़ॉल्ट): कोई अनुकूलन नहीं।

  • -Oया -O1(एक ही बात): ऑप्टिमाइज़ करें, लेकिन बहुत अधिक समय न दें।

  • -O2: अधिक आक्रामक तरीके से अनुकूलन करें

  • -O3: सबसे आक्रामक तरीके से अनुकूलन करें

  • -Ofast: के बराबर -O3 -ffast-math-ffast-mathगैर-मानक-अनुपालन फ्लोटिंग बिंदु अनुकूलन को ट्रिगर करता है। यह संकलक को यह दिखावा करने की अनुमति देता है कि फ्लोटिंग पॉइंट नंबर असीम रूप से सटीक हैं, और उन पर बीजगणित वास्तविक संख्या बीजगणित के मानक नियमों का पालन करता है। यह संकलक को यह भी बताता है कि हार्डवेयर को शून्य और फ्लोर्मल को शून्य में मानने के लिए कहें, कम से कम कुछ प्रोसेसर पर, x86 और x86-64 सहित। डेनफॉर्मल्स कई एफपीयू पर धीमी गति से ट्रिगर करते हैं, और इसलिए उन्हें शून्य के रूप में मानते हैं (जो धीमी गति को ट्रिगर नहीं करता है) एक बड़ी प्रदर्शन जीत हो सकती है।

  • -Os: कोड आकार के लिए ऑप्टिमाइज़ करें। यह वास्तव में बेहतर I-cache व्यवहार के कारण कुछ मामलों में गति में सुधार कर सकता है।

  • -Og: ऑप्टिमाइज़ करें, लेकिन डिबगिंग में हस्तक्षेप न करें। यह डिबग बिल्ड के लिए गैर-शर्मनाक प्रदर्शन सक्षम करता है और डीबग बिल्ड के लिए प्रतिस्थापित करने का इरादा रखता -O0है।

ऐसे अन्य विकल्प भी हैं जो इनमें से किसी भी सक्षम नहीं हैं, और इन्हें अलग से सक्षम किया जाना चाहिए। एक अनुकूलन विकल्प का उपयोग करना भी संभव है, लेकिन इस अनुकूलन द्वारा सक्षम विशिष्ट झंडे अक्षम करें।

अधिक जानकारी के लिए, जीसीसी वेबसाइट देखें।


वास्तव में, अन्य उत्तरों के लिए उचित होने के बावजूद, न तो -Ofast और न ही -Og मौजूद थे, जब वे उत्तर लिखे गए थे।
जनाब

तो -O100फिर संकलन क्यों करता है ?
einpoklum

3
@einpoklum क्योंकि GCC, -O3 के ऊपर -O3 के बराबर सब कुछ मानता है।
डेमी

दुर्भाग्य से, आपको अभी भी डीओजी के साथ डिबगर में <अनुकूलित आउट> का एक टन मिलता है। कदम अभी भी बेतरतीब ढंग से चारों ओर कूदता है। यह बेकार है IMHO।
doug65536 5

3

चार (0-3): जीसीसी 4.4.2 देखें मैनुअल । उच्चतर कुछ भी -O3 है, लेकिन कुछ बिंदु पर आप चर आकार की सीमा को पार कर जाएंगे।


मैंने अपने उत्तर में स्रोत कोड का पता लगाया है और आपसे सहमत हूं। अधिकता से, जीसीसी एक atoiअपरिभाषित व्यवहार पर भरोसा करने लगता है , इसके बाद 255आंतरिक सीमा होती है।
सिरो सेंटिल्ली 郝海东 冠状 iro 事件 法轮功

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