दिलचस्प पोस्ट
जावा: एआरएम्स जैसे PHP के शामिल होने के लिए फ़ंक्शन ()? परीक्षण के लिए फ़ंक्शन यदि कोई सदिश में कोई तत्व शामिल होता है Sys.stdout.flush () विधि का उपयोग संकलक द्वारा उपयोग किए गए C ++ मानक के संस्करण का निर्धारण कैसे करें? पीआईपी स्थापित mysql- अजगर पर्यावरण के साथ विफल रहता है त्रुटि: mysql_config नहीं मिला मैं रूट विशेषाधिकारों के बिना पर्ल मॉड्यूल कैसे स्थापित कर सकता हूं? प्रमुख संख्याओं को ढूंढने के लिए कार्यक्रम मैं ज्येथोन में विभिन्न पायथन लाइब्रेरी कैसे स्थापित कर सकता हूं? स्ट्रिंग (पायथन) में प्रत्येक शब्द के पहले अक्षर को कैपिटल कैसे करें? दुर्भाग्य से MyApp बंद कर दिया है इसे कैसे हल किया जा सकता है? वेबएपीआई एकाधिक रख / पोस्ट मापदंडों एंड्रॉइड में AsyncTask से एक मूल्य लौटाएं फ़ोल्डर्स / फ़ाइलों को अनदेखा करते हैं, जब Directory.GetFiles () को एक्सेस से इनकार कर दिया जाता है सादे जावास्क्रिप्ट के साथ div ऊंचाई प्राप्त करें IE7 में जावास्क्रिप्ट डीबग करना

सीमित कीवर्ड का अर्थ C ++ में है?

मैं हमेशा अनिश्चित था, प्रतिबंधित कीवर्ड का मतलब C ++ में क्या होता है?

क्या इसका मतलब यह है कि फ़ंक्शन पर दिए गए दो या अधिक सूचक ओवरलैप नहीं हैं? इसका और क्या मतलब है?

वेब के समाधान से एकत्रित समाधान "सीमित कीवर्ड का अर्थ C ++ में है?"

अपने पेपर में, मेमोरी ऑप्टिमाइज़ेशन , क्रिस्टर एरिकसन का कहना है कि restrict समय सी ++ मानक का हिस्सा नहीं है, लेकिन यह कई कंपाइलर द्वारा समर्थित है और जब यह उपलब्ध है तब इसका इस्तेमाल करने की सलाह देते हैं:

कीवर्ड को प्रतिबंधित करें

! 1999 एएनएसआई / आईएसओ सी मानक के लिए नया

! अभी तक सी ++ मानक में नहीं है, लेकिन कई सी ++ कंपाइलर द्वारा समर्थित है

! केवल एक संकेत, ऐसा कुछ भी नहीं कर सकता है और अभी भी अनुरूप होना चाहिए

एक प्रतिबंधित योग्य सूचक (या संदर्भ) …

! … मूल रूप से कंपाइलर के लिए एक वादा है कि सूचक के दायरे के लिए, सूचक का लक्ष्य केवल उस सूचक के माध्यम से पहुंचा जा सकता है (और उसमें प्रतिलिपि की गई प्रतियों)।

सी ++ कंपाइलर में जो इसे समर्थन करते हैं, यह शायद सी के समान व्यवहार करना चाहिए।

विवरण के लिए यह इतना पोस्ट देखें: C99 'प्रतिबंधित' कीवर्ड का यथार्थवादी उपयोग?

एरिकसन के पेपर के माध्यम से स्किम करने के लिए आधे घंटे का समय लें, यह दिलचस्प है और समय के लायक है।

संपादित करें

मुझे यह भी पता चला है कि आईबीएम का ऐक्स सी / सी ++ कंपाइलर __restrict__ कीवर्ड का समर्थन करता है ।

जी ++ भी इसका समर्थन करता है क्योंकि निम्न प्रोग्राम g ++ पर ठीक से संकलित करता है:

 #include <stdio.h> int foo(int * __restrict__ a, int * __restrict__ b) { return *a + *b; } int main(void) { int a = 1, b = 1, c; c = foo(&a, &b); printf("c == %d\n", c); return 0; } 

मुझे restrict के उपयोग पर एक अच्छा लेख भी मिला:

विनियमित खोजशब्द को रोकना

EDIT2

मैं एक ऐसे लेख में भाग गया, जो विशेष रूप से सी ++ प्रोग्राम में प्रतिबंधित करने के उपयोग की चर्चा करता है:

लोड-हिट-स्टोर्स और __restrict कीवर्ड

इसके अलावा, माइक्रोसॉफ्ट विज़ुअल सी ++ भी __restrict कीवर्ड का समर्थन करता है ।

जैसा कि दूसरों ने कहा, अगर सी + 14 के रूप में कुछ भी नहीं है , तो चलो __restrict__ विस्तार को __restrict__ जो कि __restrict__ के समान है

C99

restrict कहता है कि दो संकेतक एक ही मेमोरी स्थान पर नहीं जा सकते। फ़ंक्शन तर्कों के लिए सबसे आम उपयोग है।

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

यदि कॉलर restrict अनुबंध का पालन नहीं करता है, तो अपरिभाषित व्यवहार

C99 N1256 ड्राफ्ट 6.7.3 / 7 "टाइप क्वालिफायर" कहता है:

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

और 6.7.3.1 "प्रतिबंधित की औपचारिक परिभाषा" में दोषपूर्ण विवरण दिया गया है।

संभव अनुकूलन

विकिपीडिया उदाहरण बहुत रोशनी है।

यह स्पष्ट रूप से दिखाता है कि यह कैसे एक विधानसभा अनुदेश को बचाने की अनुमति देता है

प्रतिबंधित किए बिना:

 void f(int *a, int *b, int *x) { *a += *x; *b += *x; } 

छद्म विधानसभा:

 load R1 ← *x ; Load the value of x pointer load R2 ← *a ; Load the value of a pointer add R2 += R1 ; Perform Addition set R2 → *a ; Update the value of a pointer ; Similarly for b, note that x is loaded twice, ; because a may be equal to x. load R1 ← *x load R2 ← *b add R2 += R1 set R2 → *b 

प्रतिबंधित के साथ:

 void fr(int *__restrict__ a, int *__restrict__ b, int *__restrict__ x); 

छद्म विधानसभा:

 load R1 ← *x load R2 ← *a add R2 += R1 set R2 → *a ; Note that x is not reloaded, ; because the compiler knows it is unchanged ; load R1 ← *x load R2 ← *b add R2 += R1 set R2 → *b 

क्या जीसीसी सचमुच ऐसा करता है?

g++ 4.8 लिनक्स x86-64:

 g++ -g -std=gnu++98 -O0 -c main.cpp objdump -S main.o 

साथ -O0 , वे वही हैं

-O3 :

 void f(int *a, int *b, int *x) { *a += *x; 0: 8b 02 mov (%rdx),%eax 2: 01 07 add %eax,(%rdi) *b += *x; 4: 8b 02 mov (%rdx),%eax 6: 01 06 add %eax,(%rsi) void fr(int *__restrict__ a, int *__restrict__ b, int *__restrict__ x) { *a += *x; 10: 8b 02 mov (%rdx),%eax 12: 01 07 add %eax,(%rdi) *b += *x; 14: 01 06 add %eax,(%rsi) 

अपरिभाषित करने के लिए, कॉलिंग सम्मेलन है:

  • rdi = पहला पैरामीटर
  • rsi = दूसरा पैरामीटर
  • rdx = तीसरा पैरामीटर

जीसीसी आउटपुट विकी लेख की तुलना में भी स्पष्ट था: 4 निर्देश बनाम 3 निर्देश।

Arrays

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

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

 void f(char *restrict p1, char *restrict p2, size_t size) { for (size_t i = 0; i < size; i++) { p1[i] = 4; p2[i] = 9; } } 

restrict होने के restrict , एक स्मार्ट कंपाइलर (या इंसान), इसे अनुकूलित कर सकता है:

 memset(p1, 4, size); memset(p2, 9, size); 

जो संभवत: अधिक कुशल है क्योंकि यह एक सभ्य libc कार्यान्वयन (जैसे glibc) पर अनुकूलित किया जा सकता है क्या प्रदर्शन के संदर्भ में std :: memcpy () या std :: copy () का उपयोग करना बेहतर है? , संभवतः SIMD निर्देशों के साथ।

बिना, प्रतिबंधित, यह अनुकूलन नहीं किया जा सकता है, उदाहरण के लिए विचार करें:

 char p1[4]; char *p2 = &p1[1]; f(p1, p2, 3); 

फिर संस्करण के for :

 p1 == {4, 4, 4, 9} 

जबकि memset संस्करण बनाता है:

 p1 == {4, 9, 9, 9} 

क्या जीसीसी सचमुच ऐसा करता है?

जीसीसी 5.2.1। लिनक्स एक्स 86-64 उबंटु 15.10:

 gcc -g -std=c99 -O0 -c main.c objdump -dr main.o 

-O0 , दोनों समान हैं

-O3 :

  • प्रतिबंधित के साथ:

     3f0: 48 85 d2 test %rdx,%rdx 3f3: 74 33 je 428 <fr+0x38> 3f5: 55 push %rbp 3f6: 53 push %rbx 3f7: 48 89 f5 mov %rsi,%rbp 3fa: be 04 00 00 00 mov $0x4,%esi 3ff: 48 89 d3 mov %rdx,%rbx 402: 48 83 ec 08 sub $0x8,%rsp 406: e8 00 00 00 00 callq 40b <fr+0x1b> 407: R_X86_64_PC32 memset-0x4 40b: 48 83 c4 08 add $0x8,%rsp 40f: 48 89 da mov %rbx,%rdx 412: 48 89 ef mov %rbp,%rdi 415: 5b pop %rbx 416: 5d pop %rbp 417: be 09 00 00 00 mov $0x9,%esi 41c: e9 00 00 00 00 jmpq 421 <fr+0x31> 41d: R_X86_64_PC32 memset-0x4 421: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 428: f3 c3 repz retq 

    उम्मीद के memset दो memset कॉल

  • प्रतिबंधित के बिना: कोई stdlib कॉल नहीं है, केवल एक 16 विररण विस्तृत पाश अनारोलिंग है जो मुझे यहां पुन: उत्पन्न करने का इरादा नहीं है 🙂

मुझे उनके बेंचमार्क के लिए धैर्य नहीं मिला है, लेकिन मुझे विश्वास है कि प्रतिबंधित संस्करण तेजी से होगा

सख्त अलियासिंग नियम

restrict कीवर्ड केवल संगत प्रकारों (जैसे दो पूर्ण int* ) के संकेतकों को प्रभावित करते हैं, क्योंकि सख्त अलियासिंग नियमों का कहना है कि असंगत प्रकारों को अलियासिंग डिफ़ॉल्ट रूप से अपरिभाषित व्यवहार है, और इसलिए संकलक यह मान सकते हैं कि ऐसा नहीं होता है और इसे ऑप्टिमाइज़ करते हैं।

देखें: सख्त अलियासिंग नियम क्या है?

क्या यह संदर्भ के लिए काम करता है?

जीसीसी डॉक्स के अनुसार यह है: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html वाक्यविन्यास के साथ:

 int &__restrict__ rref 

सदस्य कार्यों के लिए भी एक संस्करण है:

 void T::fn () __restrict__ 

कुछ भी तो नहीं। यह C99 मानक में जोड़ा गया था

यह इस कीवर्ड को जोड़ने का मूल प्रस्ताव है जैसा कि दुर्भाग्य से बताया गया है, यह एक C99 फीचर है; इसका सी ++ के साथ कुछ नहीं करना है

सी ++ में कोई ऐसा शब्द नहीं है सी ++ कीवर्ड की सूची सी ++ भाषा मानक के खंड 2.11 / 1 में पाई जा सकती है। restrict सी भाषा के C99 संस्करण में एक कीवर्ड है और सी ++ में नहीं।

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