2013-01-24 27 views
16

कहो मैं कोड के इस स्निपेट था:क्या कंप्यूटर्स स्वचालित रूप से गणितीय कार्यों में बार-बार कॉल अनुकूलित करते हैं?

#include <cmath> 

// ... 

float f = rand(); 
std::cout << sin(f) << " " << sin(f); 

sin(f) के रूप में एक अच्छी तरह से परिभाषित समारोह वहाँ एक आसान अनुकूलन है है:

float f = rand(); 
float sin_f = sin(f); 
std::cout << sin_f << " " << sin_f; 

इस एक अनुकूलन है कि यह एक आधुनिक सी उम्मीद करना उचित है है ++ संकलक खुद से करना है? या संकलक के लिए sin(f) को f के बराबर मान के लिए हमेशा वही मान वापस करना चाहिए?

+2

जब तक एक ही संकलन इकाई में 'पाप' परिभाषित नहीं किया जाता है, तब तक संकलक नहीं जानता कि' पाप 'कैसे लागू किया जाता है, इसलिए सबसे अच्छा यह लिंक समय पर होगा। – Thomas

+2

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

+0

अनुकूलन वास्तव में जीसीसी के साथ किया जाता है। –

उत्तर

18

जी ++ डिफ़ॉल्ट अनुकूलन झंडे के साथ बनाया का उपयोग करना:

float f = rand(); 
40117e: e8 75 01 00 00   call 4012f8 <_rand> 
401183: 89 44 24 1c    mov %eax,0x1c(%esp) 
401187: db 44 24 1c    fildl 0x1c(%esp) 
40118b: d9 5c 24 2c    fstps 0x2c(%esp) 
std::cout << sin(f) << " " << sin(f); 
40118f: d9 44 24 2c    flds 0x2c(%esp) 
401193: dd 1c 24    fstpl (%esp) 
401196: e8 65 01 00 00   call 401300 <_sin> <----- 1st call 
40119b: dd 5c 24 10    fstpl 0x10(%esp) 
40119f: d9 44 24 2c    flds 0x2c(%esp) 
4011a3: dd 1c 24    fstpl (%esp) 
4011a6: e8 55 01 00 00   call 401300 <_sin> <----- 2nd call 
4011ab: dd 5c 24 04    fstpl 0x4(%esp) 
4011af: c7 04 24 e8 60 40 00 movl $0x4060e8,(%esp) 

-O2 के साथ बनाया गया:

float f = rand(); 
4011af: e8 24 01 00 00   call 4012d8 <_rand> 
4011b4: 89 44 24 1c    mov %eax,0x1c(%esp) 
4011b8: db 44 24 1c    fildl 0x1c(%esp) 
std::cout << sin(f) << " " << sin(f); 
4011bc: dd 1c 24    fstpl (%esp) 
4011bf: e8 1c 01 00 00   call 4012e0 <_sin> <----- 1 call 

से यह हम देख सकते हैं कि अनुकूलन के बिना कंपाइलर 2 कॉल का उपयोग करता है और ऑप्टिमाइज़ेशन के साथ केवल 1, अनुभवी मुझे लगता है, हम कह सकते हैं कि कंपाइलर टी को अनुकूलित करता है वह फोन करता है

17

मैं अमानक शुद्ध विशेषता के साथ काफी हद तक निश्चित जीसीसी के निशान हूँ sin, यानी __attribute__ ((pure));

यह निम्न प्रभाव पड़ता है:

कई कार्यों वापसी मान और उनकी वापसी को छोड़कर कोई प्रभाव है मूल्य केवल पैरामीटर और/या वैश्विक चर पर निर्भर करता है। ऐसा एक कार्य सामान्य सबएक्सप्रेस हटाना और लूप ऑप्टिमाइज़ेशन के अधीन हो सकता है जैसे एक अंकगणितीय ऑपरेटर होगा।

http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

और इसलिए वहाँ एक बहुत अच्छा मौका है कि इस तरह शुद्ध कॉल आम उपसूचक उन्मूलन के साथ अनुकूलित किया जाएगा।

(अद्यतन: वास्तव में cmath constexpr उपयोग कर रहा है, जो एक ही अनुकूलन का तात्पर्य है)

+0

बस इसमें जोड़ने के लिए, एमएससी कुछ ऐसे कार्यों के बारे में जानता है और कोड के अनुसार इनलाइन उत्पन्न कर सकते हैं। –

+0

'constexpr' _not_ शुद्ध शुद्ध करता है। एक अनुरूप 'constexpr' को कार्यान्वित करना संभव है जो कुछ इनपुट के लिए यादृच्छिक रूप से अपवाद फेंकता है। –

+1

जीसीसी भी अनुकूलित करता है यदि आप केवल शामिल करते हैं जिसमें कोई विशेषता नहीं है, यह आंतरिक रूप से उनके बारे में जानता है, और पाप को "कॉन्स्ट" के रूप में चिह्नित करता है जब तक कि आप पास-मैथ पास नहीं करते जहां यह केवल "शुद्ध" होता है। –