2013-02-22 16 views
8

तो मेरे लिए सटीक समय महत्वपूर्ण है, और मैं सी ++ 11 में निर्दिष्ट 3 प्रकार के घड़ियों की जांच कर रहा था, अर्थात् system_clock, steady_clock, और high_resolution_clock। मेरी प्रारंभिक चिंता परीक्षण कर रही थी अगर विभिन्न प्रकार के घड़ियों पर कॉल ओवरहेड में कोई अंतर होता है, और प्रत्येक प्रकार की घड़ी के समाधान की जांच करने के लिए।सी ++ 11 घड़ियां: g ++ steady_clock :: is_steady == झूठी?

#include <chrono> 
#include <cstdio> 
using namespace std; 
using namespace std::chrono; 

int main(int argc, char **argv) 
{ 
    size_t N = 1e6; 
    if(2 == argc) { 
    sscanf(argv[1], "%zu", &N); 
    } 

#if defined(hrc) 
    typedef high_resolution_clock clock; 
#warning "High resolution clock" 
#elif defined(sc) 
    typedef steady_clock clock; 
#warning "Steady clock" 
#elif defined(sys) 
    typedef system_clock clock; 
#warning "System clock" 
#endif 

    const double resolution = double(clock::period::num)/double(clock::period::den); 

    printf("clock::period: %lf us.\n", resolution*1e6); 
    printf("clock::is_steady: %s\n", clock::is_steady ? "yes" : "no"); 
    printf("Calling clock::now() %zu times...\n", N); 

    // first, warm up 
    for(size_t i=0; i<100; ++i) { 
    time_point<clock> t = clock::now(); 
    } 

    // loop N times 
    time_point<clock> start = clock::now(); 
    for(size_t i=0; i<N; ++i) { 
    time_point<clock> t = clock::now(); 
    } 
    time_point<clock> end = clock::now(); 

    // display duration 
    duration<double> time_span = duration_cast<duration<double>>(end-start); 
    const double sec = time_span.count(); 
    const double ns_it = sec*1e9/N; 
    printf("That took %lf seconds. That's %lf ns/iteration.\n", sec, ns_it); 

    return 0; 
} 

मैं साथ

$ g++-4.7 -std=c++11 -Dhrc chrono.cpp -o hrc_chrono 
chrono.cpp:15:2: warning: #warning "High resolution clock" [-Wcpp] 
$ g++-4.7 -std=c++11 -Dsys chrono.cpp -o sys_chrono 
chrono.cpp:15:2: warning: #warning "System clock" [-Wcpp] 
$ g++-4.7 -std=c++11 -Dsc chrono.cpp -o sc_chrono 
chrono.cpp:15:2: warning: #warning "Steady clock" [-Wcpp] 

मैं जी ++ 4.7.2 के साथ संकलित यह संकलन, और

  • SUSE लाइनेक्स, कर्नेल v3.1.10 पर भाग गया: यहाँ मेरी नमूना कार्यक्रम है , सीपीयू i7
  • एंगस्ट्रॉम लिनक्स एम्बेडेड सिस्टम, कर्नेल v3.1.10, एमसीयू टेग्रा 2 (एआरएम कॉर्टेक्स ए 9)।

पहली आश्चर्यजनक बात यह थी कि 3 प्रकार की घड़ी स्पष्ट रूप से समानार्थी हैं। उनके पास एक ही अवधि (1 माइक्रो सेकंड) है, और समय/कॉल व्यावहारिक रूप से वही है। 3 प्रकार के घड़ियों को निर्दिष्ट करने का क्या मतलब है यदि वे सभी समान हैं? क्या यह सिर्फ इसलिए है क्योंकि chrono का G ++ कार्यान्वयन अभी तक परिपक्व नहीं है? या शायद 3.1.10 कर्नेल में केवल एक उपयोगकर्ता-सुलभ घड़ी है?

दूसरा आश्चर्य, और यह बहुत बड़ा है, steady_clock :: is_steady == false है। मैं काफी हद तक निश्चित हूं कि परिभाषा के अनुसार, वह संपत्ति सच होनी चाहिए। क्या देता है?? मैं इसके आसपास कैसे काम कर सकता हूं (यानी, एक स्थिर घड़ी प्राप्त करें)?

यदि आप अन्य प्लेटफ़ॉर्म/कंपाइलर्स पर सरल प्रोग्राम चला सकते हैं, तो मुझे परिणाम जानने में बहुत दिलचस्पी होगी। किसी को भी सोच रहा है, तो यह मेरे कोर i7 पर लगभग 25 एनएस/यात्रा है, और 1000 एनएस/Tegra 2.

+0

उम्म, हाँ। मैं प्रत्येक बार घड़ी के लिए कोड को 3 बार संकलित कर रहा हूं, जिसे '-DXXX' ध्वज द्वारा निर्दिष्ट किया गया है। 'G ++ 'का अंतिम तर्क केवल निष्पादन योग्य फ़ाइल नाम है, जो किसी चाटना से कोई फर्क नहीं पड़ता। (हालांकि मैंने यह देखा है कि किस प्रकार की घड़ी और तथ्य यह है कि कार्यक्रम क्रोनो लाइब्रेरी का उपयोग कर रहा है।) –

+0

क्षमा करें, मैं कमांड लाइन –

उत्तर

8

steady_clock जीसीसी 4.7 के लिए समर्थित है (के रूप में 4 के लिए डॉक्स द्वारा दिखाए गए:

यहाँ समर्थन चेकलिस्ट के प्रासंगिक अनुभाग है।7 रिलीज: http://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/manual/manual/status.html#status.iso.2011) और stead_clock::is_steady सच है लेकिन केवल तभी जब आप --enable-libstdcxx-time=rt

साथ जीसीसी का निर्माण कि विन्यास विकल्प के विवरण के लिए https://stackoverflow.com/a/12961816/981959 देखें।

जीसीसी 4.9 के लिए यह अपने आप आपके ओएस और सी पुस्तकालय clock_gettime के लिए POSIX monotonic घड़ियों (जो glibc 2.17 या बाद में और Solaris 10 के लिए जीएनयू/लिनक्स के लिए सच है, IIRC)

यहाँ का समर्थन करता है यदि सक्षम हो जाएगा जीसीसी 4.8 के साथ परिणाम एक AMD Phenom द्वितीय X4 905e, 2.5GHz पर --enable-libstdcxx-time=rt के साथ विन्यस्त लेकिन मुझे लगता है कि 800 मेगाहर्ट्ज के लिए अभी से रोक दिए है, लिनक्स 3.6.11 चल रहा है, glibc 2,15

$ ./hrc 
clock::period: 0.001000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.069646 seconds. That's 69.645928 ns/iteration. 
$ ./sys 
clock::period: 0.001000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.062535 seconds. That's 62.534986 ns/iteration. 
$ ./sc 
clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.065684 seconds. That's 65.683730 ns/iteration. 

और बिना जीसीसी 4.7 साथ --enable-libstdcxx-time (तो वही पुनः सभी तीन घड़ी प्रकारों के लिए sults) ARMv7 Exynos5 पर लिनक्स 3.4.0 चल रहा है, glibc 2.16

clock::period: 1.000000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 1.089904 seconds. That's 1089.904000 ns/iteration. 
+1

मैं आपके एक संग्रहीत ईमेल (http://gcc.gnu.org/ml/libstdc++/2012-05/msg00085.html) में देखता हूं कि "जीएनयू पर अधिकतम घड़ी रिज़ॉल्यूशन प्राप्त करने के लिए/लिनक्स यह अभी भी उपयोग करने के लिए आवश्यक है --enable-libstdcxx-time = rt, में प्रदर्शन प्रदर्शन को _causing, libstdC++ का उपयोग करने वाले सिंगल-थ्रेडेड कोड ._ "क्या आप निर्दिष्ट कर सकते हैं कि आपका क्या मतलब है (यानी, किस ऑपरेशन में प्रदर्शन होगा?) और आप निष्कर्ष पर कैसे पहुंचे (यानी, क्या आपने प्रोफ़ाइल बनाई?)? –

+2

उस मेल का पहला पैराग्राफ देखें: _ कारण यह है कि इनमें से कुछ या सभी कॉल लाइब्रेट में परिभाषित हैं, लेकिन जीएनयू/लिनक्स पर libstdC++। इसलिए librt.so से लिंक है, तो यह libpthread.so से भी लिंक करता है और इसलिए __gthread_active_p () एकल-थ्रेडेड ऐप्स में अतिरिक्त लॉकिंग के कारण हमेशा सत्य लौट आएगा ._ libstdC++ में संदर्भ गिनती प्रोग्राम में परमाणु ओप या म्यूटेक्स का उपयोग करेगा जो एकाधिक थ्रेड का उपयोग करती है, यह निर्धारित करता है कि प्रोग्राम libpthread से लिंक करता है या नहीं। –

7

पर यात्रा आप अन्य प्लेटफार्मों/compilers पर साधारण प्रोग्राम चला सकते हैं, तो मैं होगा बहुत परिणामों को जानने में रुचि रखते हैं।

मैक ओएस एक्स 10.8, बजना ++/libC++, -O3, 2.8 गीगा Core i5:

High resolution clock 

clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.021833 seconds. That's 21.832827 ns/iteration. 

System clock 

clock::period: 1.000000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.041930 seconds. That's 41.930000 ns/iteration. 

Steady clock 

clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.021478 seconds. That's 21.477953 ns/iteration. 

steady_clock और system_clock भिन्न प्रकार होना भी आवश्यक है। steady_clock::is_steadytrue होने की आवश्यकता है। high_resolution_clocksteady_clock या system_clock का एक विशिष्ट प्रकार या उपनाम हो सकता है। system_clock::rep एक हस्ताक्षरित प्रकार होना चाहिए।

4

GNU's site के अनुसार, जीएनयू libstdC++ steady_clock का समर्थन नहीं करता है। यही कारण है कि steady_clock::is_steady गलत है।

20.11.7.1 Class system_clock   Y 
20.11.7.2 Class steady_clock   N Support old monotonic_clock spec instead 
20.11.7.3 Class high_resolution_clock Y 
+0

आह को पूरी तरह से गलत तरीके से पढ़ता हूं, ठीक है, मुझे ऐसा कुछ संदेह है। कम से कम यह अभी भी एकान्त है यदि मैं इसे सही पढ़ रहा हूं। –

+2

उन दस्तावेज़ों की तारीख पुरानी है, 'steady_clock' _is_ जीसीसी 4.7 के लिए समर्थित है, लेकिन केवल अगर आप' --enable-libstdcxx-time ' –

+3

के साथ जीसीसी बनाते हैं तो टिप्पणी _doesn't_ कहती है कि यह एकान्त नहीं है, यह कहता है कि कक्षा का पुराना नाम है पहले सी ++ 0x ड्राफ्ट से 'monotonic_clock' ... वास्तव में यह जीसीसी 4.7 और बाद में सत्य नहीं है, दस्तावेज़ महीने से बाहर हैं, कक्षा को' steady_clock' कहा जाता है लेकिन 'is_steady' केवल सत्य है जब' - सक्षम-libstdcxx-time' का उपयोग किया जाता है –