2014-10-04 6 views
6

यह code example इच्छा उत्पादन time: 0N का मूल्य की परवाह किए बिना जब विजुअल स्टूडियो प्रोफेशनल 2013 रिलीज मोड में अद्यतन 3, दोनों 32 और 64-बिट विकल्प के साथ संकलित:क्या आप इस दृश्य सी ++ बग को सीटाइम के साथ पुन: पेश या समझा सकते हैं?

#include <iostream> 
#include <functional> 
#include <ctime> 

using namespace std; 

void bar(int i, int& x, int& y) {x = i%13; y = i%23;} 

int g(int N = 1E9) { 
    int x, y; 
    int r = 0; 

    for (int i = 1; i <= N; ++i) { 
    bar(i, x, y); 
    r += x+y; 
    } 

    return r; 
} 

int main() 
{ 
    auto t0 = clock(); 
    auto r = g(); 
    auto t1 = clock(); 

    cout << r << " time: " << t1-t0 << endl; 

    return 0; 
} 

जब जीसीसी, बजना और दूसरे संस्करण के साथ परीक्षण किया rextester.com पर vC++ का, यह सही से व्यवहार करता है और शून्य से अधिक time आउटपुट करता है। कोई संकेत क्या है यहाँ क्या चल रहा है?

मैंने देखा है कि g() समारोह को इनलाइन सही व्यवहार पुनर्स्थापित करता है, लेकिन बदलते t0, r और t1 की घोषणा और प्रारंभ आदेश नहीं करता है।

+3

ऑपरेशन करने का समय घड़ी घड़ी() को कॉल करते समय टाइमर का उपयोग कर रहा है। मैंने हाल ही में एक उत्तर लिखा है जो आपको विंडोज पर उच्च रिज़ॉल्यूशन टाइमर का उपयोग करने का विचार दे सकता है: http://stackoverflow.com/questions/25954602/ctimespan-always-gets-zero –

+0

एन = 2147483646 आज़माएं और देखें कि क्या यह बनाता है अंतर। –

+0

@MichaelPetch _ ऑपरेशन करने के लिए समय टाइमर_ के संकल्प के नीचे है - यह मामला नहीं है, मैंने बड़ी 'N' की कोशिश की, जहां' f() 'निष्पादित करने में कई सेकंड लगते हैं। –

उत्तर

9

यदि आप डिबगर का उपयोग करके डिस्सेप्टर्स विंडडो को देखते हैं तो आप जेनरेट कोड देख सकते हैं। विधानसभा के पहले 4 लाइनों आप देख सकते हैं कि दो कॉल करने के लिए clock (ds:[0AF30E0h]) g करने के लिए कॉल से पहले हो से

00AF1310 push  edi 
    auto t0 = clock(); 
00AF1311 call  dword ptr ds:[0AF30E0h] 
00AF1317 mov   edi,eax 
    auto r = g(); 
    auto t1 = clock(); 
00AF1319 call  dword ptr ds:[0AF30E0h] 

    cout << r << " time: " << t1-t0 << endl; 
00AF131F push  dword ptr ds:[0AF3040h] 
00AF1325 sub   eax,edi 
00AF1327 push  eax 
00AF1328 call  g (0AF1270h) 
00AF132D mov   ecx,dword ptr ds:[0AF3058h] 
00AF1333 push  eax 
00AF1334 call  dword ptr ds:[0AF3030h] 
00AF133A mov   ecx,eax 
00AF133C call  std::operator<<<std::char_traits<char> > (0AF17F0h) 
00AF1341 mov   ecx,eax 
00AF1343 call  dword ptr ds:[0AF302Ch] 
00AF1349 mov   ecx,eax 
00AF134B call  dword ptr ds:[0AF3034h] 

: VS2012 रिलीज़ मोड में व्यक्त के लिए आप इस मिलता है। इसलिए इस मामले में इससे कोई फर्क नहीं पड़ता कि g कितना समय लगता है, नतीजा केवल उन दो अनुक्रमिक कॉलों के बीच का समय दिखाएगा।

ऐसा लगता है कि वीएस ने निर्धारित किया है कि g का कोई साइड इफेक्ट नहीं है जो clock को प्रभावित करेगा, इसलिए कॉल को स्थानांतरित करना सुरक्षित है।

जैसा कि माइकल पेटच टिप्पणियों में बताते हैं, volatiler की घोषणा के लिए कॉलर को कॉल को स्थानांतरित करने से रोक देगा।

+1

'आर' को 'अस्थिर' के रूप में चिह्नित करना शायद उस व्यवहार को बदलने के लिए संकलक के लिए पर्याप्त होगा। मुझे उम्मीद है कि यह काम करेगा 'अस्थिर ऑटो आर = जी(); ' –

+0

क्या यह कानूनी है? इस तर्क के बाद, लगभग सभी गणनाएं 'घड़ी' को प्रभावित नहीं करती हैं, इसलिए इसे कंपाइलर द्वारा कहीं भी स्थानांतरित किया जा सकता है, लेकिन यह एक पागल पागलपन होगा। –

+0

@ माइकलपेट आप सही हैं - ऐसा करता है - मैं इसे उत्तर में जोड़ दूंगा। –

संबंधित मुद्दे